1

I am using aerospike as cache in my java project. I changed the package of one of my cached objects. I have deployed new code on one machine. Getting serialize exception as old cached objects are there in the cache.

I want old code to run on some machines and new on some and both should be able to get/put objects in the aerospike cache.

Is there a way to achieve this? Why exactly am i getting this exception.

Sachin Sharma
  • 1,446
  • 4
  • 18
  • 37
  • [this link](http://stackoverflow.com/questions/30795262/redis-serialization-and-deserialization) may help you, you have to define serialVersionUID for the class. – sel-fish May 21 '16 at 12:11

3 Answers3

2

You can subclass the ObjectInputStream and use that to intercept the readClassDescriptor, and if the package of the class being deserialised differs from yours you can change it. However, it gets more complicated if the class being deserialised then contains other classes that require derserialisation.

public class MyObjectInputStream extends ObjectInputStream {

    public MyObjectInputStream(InputStream in) throws IOException {
        super(in);
    }

    @Override
    protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
        ObjectStreamClass resultClassDescriptor = super.readClassDescriptor();
        String className = resultClassDescriptor.getName();
        if (className.equals("my.old.pacakgename.MyClass")) {
            return ObjectStreamClass.lookup(MyClass.class);
        }
        return resultClassDescriptor;
    }
}

To use this

ObjectInputStream ois = new MyObjectInputStream(stream);
MyClass myObject = (MyClass) ois.readObject();
Agent96
  • 445
  • 1
  • 5
  • 20
1

The package to which a class belongs is a fundamental part of that class's identity, as reflected by the package name being part of the class's fully-qualified name. For all practical intents and purposes, changing the package to which a class is assigned drops the original class and replaces it with a completely different class.

In particular, if you serialize an instance of a class named "my.package.MyClass" via Java serialization, then successfully deserializing the result always yields an instance of a class named "my.package.MyClass". If no such class can be loaded, or if the serialization version of the one that is loaded does not match that of the one that was serialized, then deserialization will fail.

If you retain the old class along with the new class then you can perhaps patch up the deserialization problem in the new version of the application. Simply be prepared for objects of the old class, and convert them to instances of the new class as soon as you deserialize them. But if you want the new version of the application to play well with the old, then you must also do the reverse when the new one serializes objects of the affected class, else you will just cause the old application to have deserialization errors. At this point, you should be considering whether changing the package name was all that important after all.

Overall, Java serialization is not well suited for object storage. It is primarily targeted at object communication. You might consider switching to an XML-, JSON-, or YAML-based serialization format, which at least you could twiddle between cache and consumer. Such a change would of course be incompatible with the old version of your application, but so, apparently, is the package change you have already performed.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
1

In general the serialization algorithm does the following:

  • It writes out the metadata of the class associated with an instance.
  • It recursively writes out the description of the superclass until it finds java.lang.object.
  • Once it finishes writing the metadata information, it then starts with the actual data associated with the instance. But this time, it starts from the topmost superclass.
  • It recursively writes the data associated with the instance, starting from the least superclass to the most-derived class.

During de-serialization it will attempt to re-instantiate the class but since the package name has been changed it can't find the class as specified within the meta data and fail.

It might be worthwhile to look at the following tool: jDeserialize. It does not instantiate any classes described in the stream; instead, it builds up an intermediate representation of the types, instances, and values. Because of this, it can analyze streams without access to the class code that generated them.

uniknow
  • 938
  • 6
  • 5