如何通过JVM角度谈谈Java的clone操作

作者:占小狼 时间:2023-10-13 09:54:40 

前言

最近在给熔断器组件增加一个降级策略(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接口,编译的时候不检查,想啥呢?

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

来源:https://www.jianshu.com/p/309f80f33190

标签:jvm,java,clone
0
投稿

猜你喜欢

  • C#数字图像处理之图像二值化(彩色变黑白)的方法

    2023-03-13 15:07:17
  • C#实现进制转换

    2021-11-22 11:52:13
  • Android搜索结果显示高亮实例(有数据滑动底部自动刷新)

    2021-09-25 22:55:07
  • Spring Boot 与 kotlin 使用Thymeleaf模板引擎渲染web视图的方法

    2022-12-26 21:09:44
  • 老生常谈java中cookie的使用

    2023-11-11 04:37:59
  • C#数组初始化简析

    2022-01-02 11:55:12
  • Android多媒体之画画板开发案例分享

    2022-11-17 11:05:08
  • Android横竖屏切换及其对应布局加载问题详解

    2023-12-17 20:45:13
  • c语言switch反汇编的实现

    2023-06-29 03:38:17
  • Android之线程池ThreadPoolExecutor的简介

    2021-06-27 02:41:25
  • C语言数据结构系列篇二叉树的遍历

    2023-12-28 03:19:03
  • Swift洗牌动画效果的实现方法

    2023-06-21 14:01:56
  • Java拦截器和过滤器的区别分析

    2021-11-06 22:28:46
  • Android开发两个activity之间传值示例详解

    2023-11-27 20:00:45
  • java理论基础Stream元素的匹配与查找

    2021-08-26 10:11:20
  • 如何解决springboot读取配置文件的中文乱码问题

    2022-09-13 22:26:42
  • vs 中C#项目读取JSON配置文件的方法

    2022-09-22 15:04:05
  • Spring Boot项目添加外部Jar包以及配置多数据源的完整步骤

    2023-10-12 13:20:39
  • C# 参数按照ASCII码从小到大排序(字典序)

    2023-03-14 22:14:11
  • Android开发之关于项目

    2023-05-08 23:38:24
  • asp之家 软件编程 m.aspxhome.com