Coding Horror : Serialization

Few days back, I came across one interesting problem regarding serialization. Mainly it was mistake made by the developer in past. Let’s see what was the problem. Actually for one of the class, Object (serialized) was written into database table. In next version of build when we are trying to deserialize the object (where there are no changes in Objects class) we are getting error as shown below .

java.io.InvalidClassException: com.kk.serialization.Foo; local class incompatible: stream classdesc serialVersionUID = 8032766569235334056, local class serialVersionUID = -8891203736201944099

When we analyzed the issue, we found that since serialVersionUID is not explicitly mentioned , JVM has calculated it. Then the question came to our mind how it was working in previous releases. Then we found that our build server migration had happened due to which JVM on which the build was happened is different from earlier JVM. This is causing change in serialVersionUID of class without any changes.

As we have identified the issue in coding we must fix the issue but there is problem here as all objects of classes are stored in DB as Blob and it is not possible for us to update the DB records which are affected. If we add serialVersionUID to class then it breaks earlier serialized object. So now the question is how we can encounter the issue. After going through discussion and online documentation we found a workaround, which has helped us to resolve the issue.

To demonstrate the workaround, I have created a class Foo whose object is created in main and then serialized into a file foo.ser on machine A

Foo Class

Main Class

Output of above TestMain main method execution is

serialVersionId : –6822847531145140066

Object Serialized successfully.

When we try to Deserialize the object on another Machine B.

Here we are getting java.io.InvalidClassException: com.kk.serialization.Foo exception which is due to different serialVersionUID. 

To have backward compatibility and to fix this error prone code we have added serialVersionUID to Foo class and to maintain backward compatibility with object stored in DB and having different serialVersionUID (generated by JVM and JVM specific) . we have to create new input Stream by extending ObjectInputStream and override readClassDescriptor method where actually we are ignoring serialVersionUID . if it is different otherwise it will work as per default implementation.

DeSerializeInputStream

Then you can use this DeSerializeInputStream input stream which will work for newly created object where serialVersionUID is present and also work for old object where serialVersionUID which is created by JVM. So now the Object deserialization code will look as shown below.

Output of above TestMain main method execution is

Object Deserialized successfully.

Note :

This is workaround which can help you for backward compatibility and introducing new serialVersionUID . Bypassing the serialization must not be a standard practice. This implementation is just to fix the serialization issue, which are introduce due to programming mistake.So avoid this kind of serialization mistake which can cost you more while supporting application.

Happy Learning!!

 

Leave a Reply

Your email address will not be published. Required fields are marked *