從JVM角度看看Java的clone騷操作

從JVM角度看看Java的clone騷操作

鎮樓小姐姐

可獲得兩大新人禮包

36份一線互聯網Java面試電子書

84個Java稀缺面試題視頻


最近在給熔斷器組件增加一個降級策略(Hystrix好像沒有這個配置),我們提供瞭如下幾種策略:

1、默認策略

2、返回常量值

3、拋出指定異常

4、執行一段groovy腳本

當然了,這些配置都是可以在平臺上配置,並立即生效的。

目前返回常量值的實現如下:

從JVM角度看看Java的clone騷操作

今天發現,如果每次都返回同一個對象,而且這個邏輯對業務來說是黑盒(業務不知道每次拿到的對象是同一個),如果對這個對象進行了操作,那肯定會影響到其它的請求,為了避免背鍋,我們需要每次返回一個新的對象,第一反應是通過clone是否可行(因為每次json的序列化也會損耗性能),但是jdk自帶的clone方法只是淺克隆,如果對象中包含了另一個複雜對象,clone出來的對象還是存在被修改的風險。

大家可以看下面一個例子:

class Master { String name; public Master(String name) { this.name = name; }}

初始化一個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("旺財", 1, master); Dog dog2 = (Dog)dog1.clone(); dog1.name = "比利"; dog1.master.name = "zj1"; System.out.println(dog2);}

最後運行一下,結果如下:

{name:旺財, age: 1, master: zj1}

dog1是原始狗,dog2是克隆出來的,但是我修改dog1的master的name時,克隆的master也跟著變化了,這顯然不行。

雖然一直都知道Object的clone方法是淺克隆,也一直沒繼續探索一下,今天碰到了就順手看下JVM的實現,好像很簡單,在jvm.cpp文件中,搜索"JVM_Clone"

從JVM角度看看Java的clone騷操作

以前一直沒用過clone這個方法,通過源碼發現在運行的時候會檢查類是否實現Cloneable接口,編譯的時候不檢查,想啥呢?

根據對象或者數據的大小,從堆中開闢一塊同等大小的內存,然後把原始對象的數據都複製到新的內存地址,對於基本類型,可以把原始值複製過來,但是對於內部對象來說,其保存的只是一個地址,複製時也是對地址的複製,最終還是指向同一個對象,所以就造成了上述的問題


分享到:


相關文章: