如何通過JVM角度談?wù)凧ava的clone操作
前言
最近在給熔斷器組件增加一個(gè)降級(jí)策略(Hystrix好像沒有這個(gè)配置),我們提供了如下幾種策略:
1、默認(rèn)策略
2、返回常量值
3、拋出指定異常
4、執(zhí)行一段groovy腳本
當(dāng)然了,這些配置都是可以在平臺(tái)上配置,并立即生效的。
目前返回常量值的實(shí)現(xiàn)如下:

今天發(fā)現(xiàn),如果每次都返回同一個(gè)對(duì)象,而且這個(gè)邏輯對(duì)業(yè)務(wù)來(lái)說是黑盒(業(yè)務(wù)不知道每次拿到的對(duì)象是同一個(gè)),如果對(duì)這個(gè)對(duì)象進(jìn)行了操作,那肯定會(huì)影響到其它的請(qǐng)求,為了避免背鍋,我們需要每次返回一個(gè)新的對(duì)象,第一反應(yīng)是通過clone是否可行(因?yàn)槊看蝚son的序列化也會(huì)損耗性能),但是jdk自帶的clone方法只是淺克隆,如果對(duì)象中包含了另一個(gè)復(fù)雜對(duì)象,clone出來(lái)的對(duì)象還是存在被修改的風(fēng)險(xiǎn)。
詳細(xì)介紹:
大家可以看下面一個(gè)例子:
class Master {
String name;
public Master(String name) {
this.name = name;
}
}
初始化一個(gè)Master類
class Dog implements Cloneable {
String name;
int age;
Master master;
public Dog(String name, int age, Master master) {
this.name = name;
this.age = age;
this.master = master;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "{name:" + name + ", age: " + age + ", master: "+ master.name + "}";
}
}
再初始化一條狗
public static void main(String[] args) throws Exception {
Master master = new Master("zj0");
Dog dog1 = new Dog("旺財(cái)", 1, master);
Dog dog2 = (Dog)dog1.clone();
dog1.name = "比利";
dog1.master.name = "zj1";
System.out.println(dog2);
}
最后運(yùn)行一下,結(jié)果如下:
{name:旺財(cái), age: 1, master: zj1}
dog1是原始狗,dog2是克隆出來(lái)的,但是我修改dog1的master的name時(shí),克隆的master也跟著變化了,這顯然不行。
雖然一直都知道Object的clone方法是淺克隆,也一直沒繼續(xù)探索一下,今天碰到了就順手看下JVM的實(shí)現(xiàn),好像很簡(jiǎn)單,在jvm.cpp文件中,搜索"JVM_Clone"

以前一直沒用過clone這個(gè)方法,通過源碼發(fā)現(xiàn)在運(yùn)行的時(shí)候會(huì)檢查類是否實(shí)現(xiàn)Cloneable接口,編譯的時(shí)候不檢查,想啥呢?
根據(jù)對(duì)象或者數(shù)據(jù)的大小,從堆中開辟一塊同等大小的內(nèi)存,然后把原始對(duì)象的數(shù)據(jù)都復(fù)制到新的內(nèi)存地址,對(duì)于基本類型,可以把原始值復(fù)制過來(lái),但是對(duì)于內(nèi)部對(duì)象來(lái)說,其保存的只是一個(gè)地址,復(fù)制時(shí)也是對(duì)地址的復(fù)制,最終還是指向同一個(gè)對(duì)象,所以就造成了上述的問題。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
SpringBoot項(xiàng)目實(shí)現(xiàn)jar包方式打包部署
SpringBoot默認(rèn)的打包方式就是jar包,本文就來(lái)介紹一下SpringBoot項(xiàng)目實(shí)現(xiàn)jar包方式打包部署,具有一定的參考價(jià)值,感興趣的可以了解一下2024-08-08
淺析如何將多個(gè)SpringBoot項(xiàng)目打包到一個(gè)Docker容器中
在現(xiàn)代軟件開發(fā)中,Docker已成為一種流行的容器化技術(shù),能夠簡(jiǎn)化應(yīng)用的部署和管理,本文將詳細(xì)介紹如何將多個(gè)Spring Boot項(xiàng)目打包到一個(gè)Docker容器中,希望對(duì)大家有所幫助2024-10-10
Java SpringBoot 使用攔截器作為權(quán)限控制的實(shí)現(xiàn)方法
這篇文章主要介紹了Java SpringBoot 使用攔截器作為權(quán)限控制的實(shí)現(xiàn),文中通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10

