Tuesday, November 27, 2012

Part IX - Effective Java - Serialization


This is the ninth and the last in the series of posts based on the book Effective Java by Joshua Bloch. In the previous post we saw best practices in using Threads in Java.

This post talks about the best practices in Serialization. This topic may not seem to appeal and/or be relevant to the many developers who are today writing Web Applications directly. What the developers need to keep in mind is that everytime they are using EJB, they are dealing with Serialization, everytime they are faced with session replication, they are dealing with serialization, everytime they are planning to cache something using an application like memcached or many of the other NoSQL databases they are dealing with Serialization. Serialization creeps in without the knowledge of the developer and so it is important to understand the best practices.

Implement Serialization Judiciously

Making a class Serializable, theoretically only requires only implementing the interface Serializable.
1.       Once a class is made serializable then it becomes very difficult to change the class without supporting all the earlier releases and this will be a tedious exercise. To circumvent this problem one will need to design and implement one’s own custom serialize method.
2.       The second problem is that everytime one deserializes the class one needs to be wary about bad data coming into the class. If not checked correctly one can end up with security issues.
3.       The testing of the class with new version of the class becomes more and more difficult.
If an alternate form of serialization like conversion to XML is available that should be considered as opposed to serialization of bytes.

Consider using a custom serialized form

If we use the default serializable format then one can never change the class.
1.       Do not accept the default serialized form without first considering whether it is appropriate
2.       Even if you decide that the default serialized form is appropriate, you often must provide a readObject to ensure invariants and security
3.       Declare an explicit serial version UID in every serializable class you write.

Write readObject methods defensively

A readObject method will be required to be implemented to validate that the class is in the right state. A malicious client can provide data which would normally not have been accepted via the constructor. Even if one validate the data after the stream a malicious program can provide the input stream for creation of the object and later modify the attributes of the class to invalid data or different data. To avoid this make a copy of the objects in the readObject method so that the original read objects can no longer be altered by the client that provided the stream.

Provide a readResolve method when necessary

A singleton class no longer remains a singleton if it implements serializable as now one will be able to create another instance by deserializing the earlier serialized class. To prevent this one needs to implement the readResolve method
1.       A readResolve method is required not only for Singletons but all classes that control instance creation on its own.
2.       Instead of creating the instances as suggested in the readObject method in the earlier topic one could return a new instance from readResolve to prevent the same problem as mentioned earlier.

Conclusion
With this we come to the end of the series of posts based on the book Effective Java by Joshua Bloch. It is wonderful book and should be read by all the Java programmers. The author comes with tons of experience in Java and the advice that they proffer in the book are extremely important to all developers.

3 comments:

Rudrangshu Das said...

Hi Sundar
Can you please elaborate on the point - that once a class implements Serializable it can't be changed.

Rudrangshu Das said...

Hi Sundar
Can you plz elaborate on this point - once a class implements Serializable it cannot be changed.

Sundarraj Kaushik said...

The problem is that once you make a class serializable, it becomes difficult to change the class as somewhere someone will have a class that is serialized with the old version of your class and if we try deserialization of the old class using the new version we will get a SerializationException. We can work around some problems using the SerializeUID. Haven't use Serialization in a big way so cannot comment much.