Java对象的深度克隆(非bean)

时间:2011-02-09 14:55:14

标签: java performance copy deep-copy cloning

我目前正在处理的项目有很多被序列化的对象,以便获得现有对象的深层副本。这可以正常工作,直到我们在运行时有多个调用,我们在组件之间有100次,200次甚至1000次调用,这就是我们遇到性能问题的地方。

复制正在克隆的这些对象的历史原因是,在不同功能下处理相同对象的两个不同组件不应相互改变,例如:在按下保存或同步按钮之前,Swing UI中的更改不应更改后端中的对象值。

我们有相当大的代码库,我想如果我基于反射编写克隆,它将比序列化更快地工作,但是由于我们复杂的对象层次结构或由于某些其他原因,这种方法是均匀的慢。

我也尝试过使用CloneUtils(sourceforge项目),它也比较慢(我们根本就没有使用Hibernate)。 Spring BeanUtils不是一个选项(我假设从文档中它只使用bean,即内省,如果我使用它,如果使用非标准访问器暴露任何字段,我们将无法复制它们)。

有任何想法,在仍然处理不同副本的同时提高性能。如果我们提供自己的复制方法而不是序列化,我们有一个选项可以加快速度,但是每次更新这些方法都有缺点,如果我们忘记了,我们可能会失去功能。

4 个答案:

答案 0 :(得分:1)

您可以通过动态类生成来避免反射,例如使用cglib。对于您使用的每个类,您将生成一个“克隆类”,其中包含副本所需的代码。如果所有字段至少是包私有的并且您将复印机类放在同一个包中,这将使反射变得不必要。你需要一个默认的ctor,也没有最后的字段。

在这里,序列化具有优势,因为它使用sun.misc.Unsafe创建对象。

在每个类中实现deepClone方法也是一种选择。它甚至可以与克隆人的想法结合起来。

答案 1 :(得分:0)

在这种情况下,只需告诉你如何提高性能:如果你还没有使用它,请使用prototype模式。你可能会获得一些性能

答案 2 :(得分:0)

我怀疑通过遵循您提到的方法,您可以做很多事情来显着提高性能。不幸的是,复制对象确实需要时间。

略微横向思考,显然取决于你拥有多少内存以及读者与写入的比例(特别是如果每​​次写入都有很多读者),如何创建副本缓存?

答案 3 :(得分:0)

您所描述的是一种管理可变状态的霰弹枪方法。尝试使克隆更快只会给你有限的改进(比如说达到一个数量级)。此外,如何克隆套接字,流或数据库连接?

您真正需要的是通过适当的命令/查询分离来重构您的应用。通过这种方式,您将了解更改对象的位置以及不更改对象的位置。如果不确定,您可以使用单元测试来验证这一点。

有许多技术可以帮助您 - 您可以将一些对象更改为不可变(因此您可以自然地共享它们,在变异上创建新副本);你可以让可变对象实现只读接口,并在GUI等中使用RO视图。