What is serialVersionUID? Impact of not defining serialVersionUID in class and avoiding InvalidClassException in java


Contents of page :
  • serialVersionUID
  • Program 1 - to Serialize Object (without serialVersionUID)>
    • Modify the Serialized class (but don’t serialize the class again)>
  • Program 2 -  to DeSerialize object - program will throw InvalidClassException>
  • Program 3 -  to Serialize Object (with serialVersionUID)>
    • Modify the Serialized class (but don’t serialize the class again)>
  • Program 4 -  to DeSerialize object - Object will be DeSerialized successfully (without InvalidClassException) >
  • SUMMARY



serialVersionUID is used for version control of object.
If we  don’t define serialVersionUID in the class, and any modification is made in class, then we won’t be able to deSerialize our class because serialVersionUID generated by java compiler for modified class will be different from old serialized object. And deserialization process will end up throwing java.io.InvalidClassException  (because of serialVersionUID mismatch)

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.

We can use eclipse to generate serialVersionUID for our class (as done in below snapshot)

How to avoid warning ‘The serializable class Employee does not declare a static final serialVersionUID field of type long’ ?
Again answer is we can use eclipse to generate serialVersionUID for our class (as mentioned in above screenshot, click on warning button on left in line 10).




If you have serialized a class & then added few fields in it and then deserialize already serialized version of class, how can you ensure that you don’t end up throwing InvalidClassException?
>Simply we need to define serialVersionUID in class.

When we Deserialize class ( class which has been modified after Serialization and also class doesn’t declare SerialVersionUID) InvalidClassException is thrown.

When we Deserialize class ( class which has been modified after Serialization and also class declare SerialVersionUID) its gets DeSerialized successfully.


Let’s discuss this interesting topic in detail with programs-

First we will serialize a class (class which implements Serialization, but we haven’t declared SerialVersionUID)

Program 1 - to Serialize Object (without serialVersionUID)>
package serDeser4AddSUID;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
/*Author : AnkitMittal  Copyright- contents must not be reproduced in any form*/
class Employee implements Serializable {
  
      //we haven’t declared SerialVersionUId  
   private Integer id;
   private String name;
  

   public Employee(Integer id, String name) {
          this.id = id;
          this.name = name;
   }
   @Override
   public String toString() {
          return "Employee [id=" + id + ", name=" + name + "]";
   }
}
public class SerializeEmployee {
   public static void main(String[] args) {
          Employee object1 = new Employee(1, "amy");
          Employee object2 = new Employee(2, "ankit");
          try {
                 OutputStream fout = new FileOutputStream("ser.txt");
                 ObjectOutput oout = new ObjectOutputStream(fout);
                 System.out.println("Serialization process has started, serializing employee objects...");
                 oout.writeObject(object1);
                 oout.writeObject(object2);
                 fout.close();
        oout.close();
                 System.out.println("Object Serialization completed.");
                
          } catch (IOException ioe) {
                 ioe.printStackTrace();
          }
   }
}
/*OUTPUT
Serialization process has started, serializing employee objects...
Object Serialization completed.
*/

Then modify class by adding one field in class, but ensure that you don’t run the Serialization process again.

Modify the Serialized class (but don’t serialize the class again)>
class Employee implements Serializable {
  
   private Integer id;
   private String name;
   private String addedField;
   public Employee(Integer id, String name) {
          this.id = id;
          this.name = name;
   }
   @Override
   public String toString() {
          return "Employee [id=" + id + ", name=" + name + "]";
   }
}

Now, we have added addedField in class which was already Serialized, let’s see in absence of SerialVersionUID whether we will be able to DeSerialize our class or not.



Program 2 -  to DeSerialize object - program will throw InvalidClassException>
package serDeser4AddSUID;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
public class DeSerializeEmployee {
  
   public static void main(String[] args){
          try{
                 InputStream fin=new FileInputStream("ser.txt");
                 ObjectInput oin=new ObjectInputStream(fin);
                
                 System.out.println("DeSerialization process has started, displaying employee objects...");
                 Employee emp;
                 while( (emp=(Employee)oin.readObject())!=null ){
                       System.out.println(emp);
                 }
                 fin.close();
       oin.close();
      
          }catch(IOException | ClassNotFoundException e){
                 e.printStackTrace();
          }
         
          System.out.println("Object deSerialization completed.");
         
         
   }
}
/*OUTPUT
DeSerialization process has started, displaying employee objects...
java.io.InvalidClassException: serDeser4AddSUID.Employee; local class incompatible: stream classdesc serialVersionUID = 4822384361417160410, local class serialVersionUID = 5590647880449995492
Object deSerialization completed.
   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 serDeser4AddSUID.DeSerializeEmployee.main(DeSerializeEmployee.java:18)
*/
DeSerialization process has ended up throwing InvalidClassException.



Now, let’s see what will happen when we declare serialVersionUID in Serializable class.


Program 3 -  to Serialize Object (with serialVersionUID)>
package serDeser4AddSUID;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
/*Author : AnkitMittal  Copyright- contents must not be reproduced in any form*/
class Employee implements Serializable {
  
   private static final long serialVersionUID = 1L;
   private Integer id;
   private String name;
  
   public Employee(Integer id, String name) {
          this.id = id;
          this.name = name;
   }
   @Override
   public String toString() {
          return "Employee [id=" + id + ", name=" + name + "]";
   }
}
public class SerializeEmployee {
   public static void main(String[] args) {
          Employee object1 = new Employee(1, "amy");
          Employee object2 = new Employee(2, "ankit");
          try {
                 OutputStream fout = new FileOutputStream("ser.txt");
                 ObjectOutput oout = new ObjectOutputStream(fout);
                 System.out.println("Serialization process has started, serializing employee objects...");
                 oout.writeObject(object1);
                 oout.writeObject(object2);
                 fout.close();
        oout.close();
                 System.out.println("Object Serialization completed.");
                
          } catch (IOException ioe) {
                 ioe.printStackTrace();
          }
   }
}
/*OUTPUT
Serialization process has started, serializing employee objects...
Object Serialization completed.
*/

Then modify class by adding one field in class, but ensure that you don’t run the Serialization process again.

Modify the Serialized class (but don’t serialize the class again)>
class Employee implements Serializable {
  
   private static final long serialVersionUID = 1L;
   private Integer id;
   private String name;
   private String addedField;
   public Employee(Integer id, String name) {
          this.id = id;
          this.name = name;
   }
   @Override
   public String toString() {
          return "Employee [id=" + id + ", name=" + name + "]";
   }
}

Now, we have added addedField in class which was already Serialized, let’s see in presence of SerialVersionUID whether we will be able to DeSerialize our class or not.


Program 4 -  to DeSerialize object - Object will be DeSerialized successfully (without InvalidClassException) >
package serDeser4AddSUID;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
public class DeSerializeEmployee {
  
   public static void main(String[] args){
          try{
                 InputStream fin=new FileInputStream("ser.txt");
                 ObjectInput oin=new ObjectInputStream(fin);
                
                 System.out.println("DeSerialization process has started, displaying employee objects...");
                 Employee emp;
                 while( (emp=(Employee)oin.readObject())!=null ){
                       System.out.println(emp);
                 }
                 fin.close();
       oin.close();
      
          }catch(IOException | ClassNotFoundException e){
                 //e.printStackTrace();
          }
         
          System.out.println("Object deSerialization completed.");
         
         
   }
}
/*OUTPUT
DeSerialization process has started, displaying employee objects...
Employee [id=1, name=amy]
Employee [id=2, name=ankit]
Object deSerialization completed.
*/
DeSerialization process has ended up successfully.



SUMMARY>

Deserialize class ( class has been modified after Serialization and also class doesn’t declare SerialVersionUID)
>Serialize a class (class which implements Serialization, but don’t declare SerialVersionUID)

>Then modify class by adding one field in class, but ensure that you don’t run the Serialization process again.

>DeSerialization process will end up throwing InvalidClassException.



Deserialize class ( class has been modified after Serialization and also class declare SerialVersionUID)
>Now, let’s see what will happen when we declare serialVersionUID in Serializable class.

>Then modify class by adding one field in class, but ensure that you don’t run the Serialization process again.

>DeSerialization process will end successfully.



RELATED LINKS>

Serialization And Deserialization Tutorial


Serializing & DeSerializing >


Customizing  Serialization process >



Interviews >




Also Read :

Core Java tutorial in detail


Collection framework Tutorial in java in detail with diagrams and programs


Exceptions Tutorial in java in detail with diagrams and programs


Thread Concurrency Tutorial


No comments:

Post a Comment