This blog is continuation of earlier post on Java serialization.
Defination
Serial Version UID is used to ensure that during deserialization the same class (that was used during serialize process) is loaded. The serialVersionUID is a universal version identifier for a Serializable class. Deserialization uses this number to ensure that a loaded class corresponds exactly to a serialized object. If no match is found, then an InvalidClassException is thrown.
Serial version UID Syntax
[ANY-ACCESS-MODIFIER] static final long serialVersionUID = 123L;
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 serial versionUID?
Lets start with annoying warning message you get in your IDE when you declare a class as Serializable. The serializable class Employee does 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.
How serialVersionUID is generated?
serial versionUID is a 64-bit hash total of the class name, interface class names, methods and fields. Serialization runtime generates a serialVersionUID if you do not add one in source. Refer this link for the algorithm to generate serialVersionUID.
It is advised to have serialVersionUID as unique as possible. That's 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.
How serial versionUID 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.
Java Class to Demonstrate this concept:
Define Employee.java as below
package serializationdemo;
import java.io.Serializable;
class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String eName;
private String eId;
public String geteName() {
return eName;
}
public void seteName(String eName) {
this.eName = eName;
}
public String geteId() {
return eId;
}
public void seteId(String eId) {
this.eId = eId;
}
Employee(String a, String b){
this.eName = a;
this.eId = b;
}
}
Refer below Code to Serialize the Employee Object
package serializationdemo;
import java.io.*;
public class EmployeeSerialDemo {
public static void main(String[] args) {
Employee c = new Employee("Suresh", "E123"); // 2
File outFile = new File("empSerial.ser");
try {
FileOutputStream fs = new FileOutputStream(outFile);
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(c); // 3
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
NewEmployeeDeserialDemo.java: This class run fine as long as serial version ID matching with Employee class.
package serializationdemo;
import java.io.*;
public class NewEmployeeDeserialDemo {
public static void main(String[] args) {
File ReadFile = new File("empSerial.ser");
try {
FileInputStream fis = new FileInputStream(ReadFile);
ObjectInputStream ois = new ObjectInputStream(fis);
Employee e = (Employee) ois.readObject();
System.out.println("Deserialized Employee name= "+ e.geteName());
System.out.println("Deserialized Employee ID= "+ e.geteId());
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Change Employee class one line to this:
private static final long serialVersionUID = 2L;
Run NewEmployeeDeserialDemo.java again to check can we deserialized our earlier serialized object. You will get following exception:
java.io.InvalidClassException: serializationdemo.Employee; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:604)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1601)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at serializationdemo.NewEmployeeDeserialDemo.main(NewEmployeeDeserialDemo.java:12)