從JVM角度看看Java的clone操做

最近在給熔斷器組件增長一個降級策略(Hystrix好像沒有這個配置),咱們提供了以下幾種策略:json

  1.  默認策略
  2.  返回常量值
  3.  拋出指定異常
  4.  執行一段groovy腳本

固然了,這些配置都是能夠在平臺上配置,並當即生效的。jvm

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

從JVM角度看看Java的clone操做

今天發現,若是每次都返回同一個對象,並且這個邏輯對業務來講是黑盒(業務不知道每次拿到的對象是同一個),若是對這個對象進行了操做,那確定會影響到其它的請求,爲了不背鍋,咱們須要每次返回一個新的對象,第一反應是經過clone是否可行(由於每次json的序列化也會損耗性能),可是jdk自帶的clone方法只是淺克隆,若是對象中包含了另外一個複雜對象,clone出來的對象仍是存在被修改的風險性能

你們能夠看下面一個例子:this

<pre style="box-sizing: border-box; font-family: inherit; font-size: 1em; margin: 1em 0px; padding: 12px 10px; white-space: pre-wrap; border: 1px solid rgb(232, 232, 232); position: relative; line-height: 1.5; color: rgb(153, 153, 153); background: rgb(244, 245, 246);">class Master {
 String name;
 public Master(String name) {
 this.name = name;
 }
}
</pre>spa

初始化一個Master類.net

<pre style="box-sizing: border-box; font-family: inherit; font-size: 1em; margin: 1em 0px; padding: 12px 10px; white-space: pre-wrap; border: 1px solid rgb(232, 232, 232); position: relative; line-height: 1.5; color: rgb(153, 153, 153); background: rgb(244, 245, 246);">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 + "}";
 }
}
</pre>對象

再初始化一條狗blog

<pre style="box-sizing: border-box; font-family: inherit; font-size: 1em; margin: 1em 0px; padding: 12px 10px; white-space: pre-wrap; border: 1px solid rgb(232, 232, 232); position: relative; line-height: 1.5; color: rgb(153, 153, 153); background: rgb(244, 245, 246);">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);
}
</pre>接口

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

<pre style="box-sizing: border-box; font-family: inherit; font-size: 1em; margin: 1em 0px; padding: 12px 10px; white-space: pre-wrap; border: 1px solid rgb(232, 232, 232); position: relative; line-height: 1.5; color: rgb(153, 153, 153); background: rgb(244, 245, 246);">{name:旺財, age: 1, master: zj1}
</pre>

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

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

從JVM角度看看Java的clone操做

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

根據對象或者數據的大小,從堆中開闢一塊同等大小的內存,而後把原始對象的數據都複製到新的內存地址,對於基本類型,能夠把原始值複製過來,可是對於內部對象來講,其保存的只是一個地址,複製時也是對地址的複製,最終仍是指向同一個對象,因此就形成了上述的問題。

相關文章
相關標籤/搜索