Deep Cloning of Java objects (Not beans)

1.3k views Asked by At

The project that I am currently working on has lot of objects that are serialized in order to get a deep copy of the the existing object. This works fine until we have multiple calls at runtime in some cased we have 100, 200, or even 1000 calls between components and this is where we are hit with performance headache.

Historical reason for copying these objects being cloned is that , two different component working on same objects under different functionality should not change each other e.g. Changes in Swing UI should not change the object values in backend until save or synchronized button is pressed.

We have quite a large code base, I thought if I would write clone based on reflection it will work faster as compared to serialization , but either due to our complex hierarchies of objects or due to some other reason , this approach is even slower.

I also tried using CloneUtils (sourceforge project) , which is slower as well (We are not using Hibernate at all). Spring BeanUtils is not an option (I assume from docs that it only uses beans i.e. introspection and in case I use it if any fields are exposed using non standard accessor , we will not be able to copy those).

Has anyone any idea , improve the performance while still working on different copies. We have an option which will speed up things in case we provide our own copy methods ,instead of serialization, but that has downside of updating these methods every time and if we forget we might loose functionality.

4

There are 4 answers

6
Cris On

Just give you a hint in how you can improve performance in cases like this: use prototype pattern if you are not already using it.You might gain some perfromance

1
Dan On

I doubt that there is that much you can do to improve performance significantly by following the approaches you have mentioned. Unfortunately it does take time to copy an object.

Thinking slightly laterally, and clearly depending on how much memory you have and also the ratio of readers to writes (especially if you have many readers for every write), how about creating a cache of copies?

2
maaartinus On

You can avoid reflection by dynamic class generation, e.g., using cglib. For each class you use, you'd generate a "cloner class" containing the code needed for the copy. This would make reflection unnecessary, provided all fields are at least package-private and you put the copier class in the same package. You'd need a default ctor and no final fields, too.

Here, serialization has an advantage, as it creates objects using sun.misc.Unsafe.

Implementing a deepClone method in each class could be an option, too. It could be even combined with the cloner-class idea.

2
ddimitrov On

What you describe is a shotgun approach to managing mutable state. Trying to make clone faster will only give you limited improvements (say up to an order of magnitude). Besides, how do you clone a socket, a stream or a database connection?

What you really need is to refactor your app with proper command/query separation. This way you will know where you are changing your objects and where you are not. You can use unit tests to verify this if not sure.

There are a number of techniques that can help you - you can change some of your objects to be immutable (so you can naturally share them, creating new copies on mutation); you can make mutable objects implement read-only interfaces and use the RO view in the GUI, etc.