The serialization at runtime associates with each serializable class a version number called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. Geek, now you must be wondering why do we use SerialVersionUID?
It is because SerialVersionUID is used to ensure that during deserialization the same class (that was used during serialize process) is loaded. Consider ran the illustration given below to get a fairer understanding of Serialization & Deserialization.
Illustration:
- Suppose a person who is in the UK and another person who is in India, are going to perform serialization and deserialization respectively. In this case, to authenticate that the receiver who is in India is the authenticated person, JVM creates a unique ID which is known as SerialVersionUID.
- In most cases, serialization and deserialization both activities are done by a single person with the same system and same location. But in serialization, sender and receiver are not the same people that is the persons may be different, machine or system may be different and location must be different then SerialVersionUID comes into the picture. In serialization, both sender and receiver should have .class file at the time of beginning only i.e. the person who is going to do serialization and the person who is ready for deserialization should contain the same .class file at the beginning time only.
Serialization at the time of serialization, with every object sender side JVM will save a Unique Identifier. JVM is responsible to generate that unique ID based on the corresponding .class file which is present in the sender system.
Deserialization at the time of deserialization, receiver side JVM will compare the unique ID associated with the Object with local class Unique ID i.e. JVM will also create a Unique ID based on the corresponding .class file which is present in the receiver system. If both unique ID matched then only deserialization will be performed. Otherwise, we will get Runtime Exception saying InvalidClassException. This unique Identifier is nothing but SerialVersionUID.
There are also certain problem associations depending on the default SerialVersionUID generated by JVM as listed below:
- Both sender and receiver should use the same JVM with respect to platform and version also. Otherwise, the receiver is unable to deserialize because of different SerialVersionUID.
- Both sender and receiver should use the same ‘.class’ file version. After serialization, if there is any change in the ‘.class’ file at the receiver side then the receiver is unable to deserialize.
- To generate SerialVersionUID internally JVM may use complex algorithms which may create performance problems.
Implementation:
We can solve the above problem by configuring our own SerialVersionUID. We can configure our own SerialVersionUID for which we need 3 classes as follows:
- Random class which contains two variables which are going to Serialize, let it be ‘Geeks’
- Class for sender side which is going to Serialize an object
- Class for receiver side which is going to deserialize
Syntax:
private static final long SerialVersionUID=10l;
Example 1:
JAVA
// Java program to illustrate Implementation of // User-defined SerialVersionUID // Main class // // Geeks which contains two variable which // are going to Serialize to // Illustrate Implementation of Serializable Interface class Geeks implements Serializable { // User-defined SerialVersionUID // Custom initialization private static final long SerialVersionUID = 10l; int i = 10 ; int j = 20 ; } |
Example 2: Class for sender side which is going to Serialize an object
JAVA
// Java program to illustrate // implementation of User-defined // SerialVersionUID // Importing required classes import java.io.*; // Sender side class which is going to Serialize object class Sender { // Main driver method public static void main(String[] args) { // Creating object of class Random class which // contains two variables which are going to // Serialize In simpler words , object of class // 'Geeks' Geeks g = new Geeks(); // Here xyz.txt is the file name where the object is // going to serialize FileOutputStream fos = new FileOutputStream( "xyz.txt" ); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(g); } } |
Example 3: Class for receiver side which is going to deserialize
JAVA
// Java program to illustrate Implementation of // User-defined SerialVersionUID // Importing I/O classes import java.io.*; // Receiver side class which is going to deserialize class Receiver { // main driver method public static void main(String[] args) { // Here xyz.txt is the file name where the object is // going to Deserialized FileInputStream fis = new FileInputStream( "xyz.txt" ); ObjectInputStream ois = new ObjectInputStream(fis); // Creating object of class 'Geeks' Geeks g1 = (Geeks)ois.readObject(); // Print and display the // deserialized object value System.out.println( "Deserialized Object Value:" + g1.i + "..." + g1.j); } } |
Output:
We can see the file which is xyz.txt where object is Serialize and also the output when we deserialize the Object.
Note: In the above program, if we perform any change to the Geeks .class file at the receiver end. We don’t get any problem at the time of deserialization. In this case, sender and receiver are not required to maintain the same JVM versions.