当前位置: 首页 > 编程笔记 >

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

申屠洛华
2023-03-14
本文向大家介绍如何通过JVM角度谈谈Java的clone操作,包括了如何通过JVM角度谈谈Java的clone操作的使用技巧和注意事项,需要的朋友参考一下

前言

最近在给熔断器组件增加一个降级策略(Hystrix好像没有这个配置),我们提供了如下几种策略:

1、默认策略

2、返回常量值

3、抛出指定异常

4、执行一段groovy脚本

当然了,这些配置都是可以在平台上配置,并立即生效的。

目前返回常量值的实现如下:


今天发现,如果每次都返回同一个对象,而且这个逻辑对业务来说是黑盒(业务不知道每次拿到的对象是同一个),如果对这个对象进行了操作,那肯定会影响到其它的请求,为了避免背锅,我们需要每次返回一个新的对象,第一反应是通过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"


以前一直没用过clone这个方法,通过源码发现在运行的时候会检查类是否实现Cloneable接口,编译的时候不检查,想啥呢?

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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持。

 类似资料:
  • 本文向大家介绍请你谈谈如何通过反射创建对象?相关面试题,主要包含被问及请你谈谈如何通过反射创建对象?时的应答技巧和注意事项,需要的朋友参考一下 考察点:类 - 方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance() - 方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Co

  • 本文向大家介绍请谈谈你对JVM的理解?相关面试题,主要包含被问及请谈谈你对JVM的理解?时的应答技巧和注意事项,需要的朋友参考一下 Java虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。 什么是字节码?采用字节码的好处是什么? 在 Java 中,JVM可以理解的代码就叫做(

  • 本文向大家介绍请你谈谈Java中是如何支持正则表达式操作的?相关面试题,主要包含被问及请你谈谈Java中是如何支持正则表达式操作的?时的应答技巧和注意事项,需要的朋友参考一下 考察点:正则表达式 Java中的String类提供了支持正则表达式操作的方法,包括:matches()、replaceAll()、replaceFirst()、split()。此外,Java中可以用Pattern类表示正则表

  • 本文向大家介绍简单谈谈Git中的回滚操作,包括了简单谈谈Git中的回滚操作的使用技巧和注意事项,需要的朋友参考一下 首先介绍下场景 首先,一定要想清楚,自己想干什么。 找redis源码作为例子,查看所在的分支git branch 取前5条commit看看 临时切换到某个commit 有可能你并不需要回滚代码,你只想将代码库暂时切换到之前的某个版本,看看那个时候的实现,然后回来继续写之前没有完成的任

  • 本文向大家介绍谈谈java的concurrent用法,包括了谈谈java的concurrent用法的使用技巧和注意事项,需要的朋友参考一下 我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常需要有程序员独立完成代码实现,当然也有一些开源的框架提供了这些功能,但是这些依然没有JDK自带的功能使用起来方便。而当针对高质量Java多线程并发程序设计时,为防止死蹦等现象的出现,比如使用jav

  • 本文向大家介绍通过一次报错详细谈谈Point事件,包括了通过一次报错详细谈谈Point事件的使用技巧和注意事项,需要的朋友参考一下 前言 这篇文章在草稿箱里躺了很久,因为最近又遇到了相关问题,于是又整理了一下。请注意这里讲的不是 css 的 pointer-events。下面话不都说了,来一起看看详细的介绍吧。 起因 从某个月黑风高的晚上开始,有人发现我们的 web-app 在 Chrome 模拟