About serialVersionUID in Java Serialization

serialVersionUID is used to ensure that during deserialization the same class (tha was used during serialize process) is loaded. This is a one line definition to explain why a serialVersionUID is used?
Apart from the above definition there are quite a few things to learn from this serialVersionUID. As per javadocs, following is format of serialVersionUID:

serialVersionUID Syntax
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
serialVersionUID is a static final field. You can assign any number of your choice to it. Later I will explain the significance of these two statements.

Why serialVersionUID?
Let’s start with annoying warning message you get in your IDE when you declare a class as
Seriablizable.

The Seriablizable class Lion does not declare a static final serialVersionUID field of type long
Most of us used to ignore this message as we always do for a warning. My general note is, always pay attention to the java warning messages. It will help you to learn a lot of fundamentals.

serialVersionUID is a must in serialization process. But it is optional for the developer to add it in java source file. If you are not going to add it in java source file, serialization runtime will generate a serialVersionUID and associate it with the class. The serialized object will contain this serialVersionUID along with other data.
Even though serialVersionUID is a static field, it gets serialized along with the object. This is one exception to the general serialization rule that, “static fields are not serialized”.

How serialVersionUID is generated?
serialVersionUID is a 64-bit hash of the class name, interface class names, methods and fields.

Serialization runtime generates a serialVersionUID if you do not add one in source.

It is advised to have serialVersionUID as unique as possible. Thats why the java runtime chose to have such a complex algorithm to generate it.

If you want help in generating it, jdk tools provides a tool named serialver. Use serialver -show to start the gui version of the tool as shown below.

How serialVersionUID works?
When an object is serialized, the serialVersionUID is serialized along with the other contents.
Later when that is deserialized, the serialVersionUID from the deserialized object is extracted and compared with the serialVersionUID of the loaded class.

If the numbers do not match then,InvalidClassException is thrown.

If the loaded class is not having a serialVersionUID declared, then it is automatically generated using the same algorithm as before.

Strongly recommended to declare serialVersionUID
Javadocs says, “the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization”

Now you know why we should declare a serialVersionUID.

Not only declaring a serialVersionUID is sufficient. You must do the following two things carefully. Otherwise it defeats the purpose of having the serialVersionUID.

serialVersionUID should be maintained. As and when you change anything in the class, you should upgrade the serailVersionUID.

Try your best to declare a unique serialVersionUID.

Demonstrate serialVersionUID
Initial class to be serialized has a serialVersionUID as 1L.
import java.io.Serializable;
public class Lion implements Serializable {
private static final long serialVersionUID = 1L;
private String sound;
public Lion(String sound) {
this.sound = sound;
}
public String getSound() {
return sound;
}
}

Test serialVersionUID:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerialVersionUIDTest {
public static void main(String args[]) throwsIOException, ClassNotFoundException {
Lion leo = new Lion(“roar”);
// serialize
System.out.println(“Serialization done.”);
FileOutputStream fos = newFileOutputStream(“serial.out”);
ObjectOutputStream oos = newObjectOutputStream(fos);
oos.writeObject(leo);
// Deserialize
FileInputStream fis = newFileInputStream(“serial.out”);
ObjectInputStream ois = newObjectInputStream(fis);
Lion deserializedObj = (Lion) ois.readObject();
System.out.println(“DeSerialization done. Lion: ” + deserializedObj.getSound());
}
}

Output:
Serialization done.
Deserialization done. Lion: roar

Now change serialVersionUID to 2L in Lion class.

private static final long serialVersionUID = 2L;
Comment the “serialize” block (4 lines of code) in SerialVersionUIDTest. Now run it and you will get the following exception.

Serialized Lion with serialVersionUID with 1L.
Changed serialVersionUID to 2L and compiled and loaded the class
Deserialize the already serialized object and load it with the latest class
We get exception as serialVersionUID is not matching.

Exception in thread “main”java.io.InvalidClassException: Lion; local classincompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at SerialVersionUIDTest.main(SerialVersionUIDTest.java:21)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: