Tuesday, 12 March 2013

serialVersionUID in java Serialization

serialVersionUID is used to ensure that same class(That was used during Serialization) is loaded during Deserialization.serialVersionUID is used for version control of object.
If you have used Serialization then You might have seen  serialVersionUID because whenever you implement Serializable interface your IDE will give you warning.

Serialversionuid Syntax:

As per java docs
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

serialVersionUID must be Static and final.You can assign any number to it.
Lets see an example:
Create Employee.java in src->org.arpit.javapostsforlearning

1.Employee.java
package org.arpit.javapostsforlearning;
import java.io.Serializable;
public class Employee implements Serializable{

         private static final long serialVersionUID = 1L;

    int employeeId;
    String employeeName;
    String department;
    
    public int getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(int employeeId) {
        this.employeeId = employeeId;
    }
    public String getEmployeeName() {
        return employeeName;
    }
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
}

Create SerializeMain.java in src->org.arpit.javapostsforlearning

2.SerializeMain.java
package org.arpit.javapostsforlearning;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
 public class SerializeMain {

 /**
  * @author Arpit Mandliya
  */
 public static void main(String[] args) {

  Employee emp = new Employee();
  emp.setEmployeeId(101);
  emp.setEmployeeName("Arpit");
  emp.setDepartment("CS");
  try
  {
   FileOutputStream fileOut = new FileOutputStream("employee.ser");
   ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
   outStream.writeObject(emp);
   outStream.close();
   fileOut.close();
  }catch(IOException i)
  {
   i.printStackTrace();
  }
 }
}
Create DeserializeMain.java in src->org.arpit.javapostsforlearning
3.DeserializeMain.java
package org.arpit.javapostsforlearning;
import java.io.IOException;
import java.io.ObjectInputStream;

public class DeserializeMain {
 /**
  * @author Arpit Mandliya
  */
 public static void main(String[] args) {
  
  Employee emp = null;
       try
       {
          FileInputStream fileIn =new FileInputStream("employee.ser");
          ObjectInputStream in = new ObjectInputStream(fileIn);
          emp = (Employee) in.readObject();
          in.close();
          fileIn.close();
       }catch(IOException i)
       {
          i.printStackTrace();
          return;
       }catch(ClassNotFoundException c)
       {
          System.out.println("Employee class not found");
          c.printStackTrace();
          return;
       }
       System.out.println("Deserialized Employee...");
       System.out.println("Emp id: " + emp.getEmployeeId());
       System.out.println("Name: " + emp.getEmployeeName());
       System.out.println("Department: " + emp.getDepartment());
 }
}

4.Run it:

First run SerializeMain.java then DeserializeMain.java and you will get following output:
Deserialized Employee...
Emp id: 101
Name: Arpit
Department: CS
So when you run program,it was completed successfully and employee.ser has been created on disk.If you again run DeserializeMain.java,it will again run successfully. Now change value of variable serial to
 private static final long serialVersionUID = 2L;
and if you now run DeserializeMain.java it will give you following error.
java.io.InvalidClassException: org.arpit.javapostsforlearning.Employee; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
So here during deserialization,we got error.It complained about Serialvesionuid being changed.But how does it know? because serialversionuid is a static variable and we know that "We can not serialize static variables".How does it store  serialversionuid? yes ,there is exception.Inspite of serialversionuid being static,it get serialized.So ObjectOutputStream writes every time to output stream and ObjectInputStream reads it back and if it does not have same values as in current version of class then it throw InvalidClassException.

Why serialversionuid is required?

In real time,It is possible that you have serialized a object in a file and you deserialized it after few months on different JVM.In between serialization and deserialization class declaration has been changed.So it is a good idea to maintain version system and serialversionid does exactly same thing.It checks if you are deserializing same object which you have serialized.

Best Practices:

Java docs 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".

So it says you must declare serialVersionUID because it give us more control.for e.g. Default rules for generating serialVersionUID can be too strict in some cases. For example when the visibility of a field changes, the serialVersionUID changes too. or sometimes you just want to forbid deserialization of old serialized object then you can just change serialVersionUID.

Is this enough?.No,you must not only declare it but also maintain it.So most important part is maintaining  serialVersionUID otherwise every thing will run without any exceptions.You should change serialVersionUID when there is some change in the definition of data stored in the class for example data type of field is changed.
 

Java tutorial for beginners Copyright © 2011 - |- Template created by O Pregador - |- Powered by Blogger Templates