从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接口,编译的时候不检查,想啥呢?

根据对象或者数据的大小,从堆中开辟一块同等大小的内存,而后把原始对象的数据都复制到新的内存地址,对于基本类型,能够把原始值复制过来,可是对于内部对象来讲,其保存的只是一个地址,复制时也是对地址的复制,最终仍是指向同一个对象,因此就形成了上述的问题。

相关文章
相关标签/搜索