In this article, we will discuss importance of SerialVersionUID in Serialization and De-Serialization process
Finally we will compare compiler generated SerialVersionUID v/s programmer defined SerialVersionUID and decide which one to use ?
In all previous articles, we haven’t discussed anything about serialVersionUID
- Introduction to Serialization
- Serializable interface in detail with example
- Transient modifier in serialization process
- Order of serialization and de-serialization
- Serialization with Aggregation
- Serialization with Inheritance
- Externalizable interface in detail with example
But there is always serialVersionUID associated with every serializable class
Eclipse IDE warning while implementing Serializable interface:
- If you are using IDE like Eclipse, then it warns with following message
- Waring : The serializable class <class-name> does not declare static final serialVersionUID field of type long
- Look at the below screen-capture for message in Eclipse IDE
- As we stated earlier that there is always a serialVersionUID associated with every serializable class, then where we have declared in earlier example ?
- Serialization: Actually, we haven’t declared this field explicitly and if it isn’t declared then compiler does job for us by declaring this static field and it get saved to serialized file along with Object values
- De-Serialization: while restoring object back from file storage, then first thing it does is, compare stored serialVersionUID inside serialized file with serializable class
- Exception: if there is a mismatch between serialVersionUID present in the serialized file and serializable class, then InvalidClassException will be thrown
Now, next question with serialVersionUID is whether to use compiler generated serialVersionUID or programmer explicitly declaring serialVersionUID i.e.;
serialVersionUID – Compiler generated v/s programmer defined:
- Compiler generated serialVersionUID is highly complex as it uses combination of class name and properties to generate this unique Id
- Due to complexity in creation of this unique Id, performance of serialization and de-serialization process becomes slow
- Therefore, it is highly recommended to define serialVersionUID inside serializable class and use for both serialization and de-serialization process
- Firstly it reduces complexity in creating compiler generated serialVersionUID and second comparing this unique Id during de-serialization process
- Also, programmer hasflexibility of declaring any Long value
Lets us see a simple demo program for both cases:
1. serialVersionUID is same
- Below customer class is a serializable class i.e.; it implements java.io.Serializable interface
- programmer provides serialVersionUID with value 19L to static variable named serialVersionUID
Customer.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package in.bench.resources.serial.version.uid; import java.io.Serializable; class Customer implements Serializable { // default serialVersionUID private static final long serialVersionUID = 19L; // member variables for Customer int customerId; String customerName; String customerSSN; // 3-arg parameterized constructor for Customer public Customer( int customerId, String customerName, String customerSSN) { super (); this .customerId = customerId; this .customerName = customerName; this .customerSSN = customerSSN; } // to print nicely - customer object @Override public String toString() { return "Customer [customerId=" + customerId + ", customerName=" + customerName + ", customerSSN=" + customerSSN + "]" ; } } |
Main class – to Serialize :
- This class is the main class which serializes Customer class
- with serialVersionUID 19L
SerializeCustomer.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | package in.bench.resources.serial.version.uid; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class SerializeCustomer { public static void main(String[] args) { // create a customer object using 3-arg parametrized constructor Customer customer = new Customer( 101 , "SJ" , "SSN-109878" ); // creating output stream variables FileOutputStream fos = null ; ObjectOutputStream oos = null ; try { // for writing or saving binary data fos = new FileOutputStream( "Customer.ser" ); // converting java-object to binary-format oos = new ObjectOutputStream(fos); // writing or saving customer object's value to stream oos.writeObject(customer); oos.flush(); oos.close(); } catch (FileNotFoundException fnfex) { fnfex.printStackTrace(); } catch (IOException ioex) { ioex.printStackTrace(); } System.out.println( "Customer object saved to Customer.ser file" ); } } |
Output:
1 | Customer object saved to Customer.ser file |
Main class – to DeSerialize :
- This class de-serializes Customer class with same serialVersionUID used for serialization i.e.; 19L
DeSerializeCustomer.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | package in.bench.resources.serial.version.uid; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; public class DeSerializeCustomer { public static void main(String[] args) { // creating input stream variables FileInputStream fis = null ; ObjectInputStream ois = null ; // creating customer object reference // to hold values after de-serialization Customer customer = null ; try { // reading binary data fis = new FileInputStream( "Customer.ser" ); // converting binary-data to java-object ois = new ObjectInputStream(fis); // reading object's value and casting to Customer class customer = (Customer) ois.readObject(); } catch (FileNotFoundException fnfex) { fnfex.printStackTrace(); } catch (IOException ioex) { ioex.printStackTrace(); } catch (ClassNotFoundException ccex) { ccex.printStackTrace(); } System.out.println( "Customer object de-serialized from " + "Customer.ser file\nLet's print to console... \n" ); // printing customer object to console using toString() method System.out.println(customer); } } |
Output:
1 2 3 4 | Customer object de-serialized from Customer.ser file Let's print to console... Customer [customerId=101, customerName=SJ, customerSSN=SSN-109878] |
2. serialVersionUID is different
Let us tweak above example by changing serialVersionUID after serialization process
- We will keep same serialVersionUID i.e.; 19L while serialization
- Change serialVersionUID after serialization
- That’s, change to 21L
- Serialization program will be executed and same output will be seen as per earlier case
- But during de-serialization process, due to the difference of serialVersionUID, runtime exception will be thrown i.e.; InvalidClassException
Steps:
- Keep same serialVersionUID (i.e.; 19L) in Customer class and execute serialize customer class
- Above step help in storing or saving customer object to serialized file
- Now, change serialVersionUID to 21L in Customer class and compile again
- Next step, execute de-serialize customer class
Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | java.io.InvalidClassException: in.bench.resources.serial.version.uid. Customer; local class incompatible: stream classdesc serialVersionUID = 19, local class serialVersionUID = 21 at java.io.ObjectStreamClass.initNonProxy( ObjectStreamClass.java:616) at java.io.ObjectInputStream.readNonProxyDesc( ObjectInputStream.java:1623) at java.io.ObjectInputStream.readClassDesc( ObjectInputStream.java:1518) at java.io.ObjectInputStream.readOrdinaryObject( ObjectInputStream.java:1774) at java.io.ObjectInputStream.readObject0( ObjectInputStream.java:1351) at java.io.ObjectInputStream.readObject( ObjectInputStream.java:371) at in.bench.resources.serial.version.uid.DeSerializeCustomer. main(DeSerializeCustomer.java:27) Customer object de-serialized from Customer.ser file Let's print to console... null |
Related Articles:
- Java – Serialization and De-Serialization Tutorial Index
- Java – Introduction to Serialization and De-Serialization
- Java – Serializable interface
- Java – Transient keyword with Serialization
- Java – Transient keyword with static variable in Serialization
- Java – Transient keyword with final variable in Serialization
- Java – Serializing a variable with transient modifier or keyword
- Java – Order of Serialization and De-Serialization
- Java – Serialization with Aggregation
- Java – Serialization with Inheritance
- Java – Externalization in detail
- Java – Serializable v/s Externalizable
- Java – Importance of SerialVersionUID in Serialization
- Java – Singleton Design pattern with Serialization
- Java – How to construct a singleton class in a multi-threaded environment ?
- Java – Singleton design pattern, restricting Object creation by overriding readResolve() method
- Java – How to stop Serialization ?
- Java – How to serialize and de-serialize ArrayList ?
- Java – Interview question & answers on Serialization and Externalization
References:
- https://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
- https://docs.oracle.com/javase/7/docs/platform/serialization/spec/serial-arch.html
- https://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html
- https://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html
- https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html
- https://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html
- http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.3
Happy Coding !!
Happy Learning !!