Java serialVersionUID – How to generate serialVersionUID

Java serialization is the process of converting an object into a stream of bytes so we can do stuff like store it on disk or send it over the network. Deserialization is the reverse process – converting a stream of bytes into an object in memory.

During serialization, java runtime associates a version number with each serializable class. This number called 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. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender’s class, then deserialization will result in an InvalidClassException.

1. Java serialVersionUID Syntax

A serializable class can declare its own serialVersionUID explicitly by declaring a field named “serialVersionUID” that must be static, final, and of type long.

private static final long serialVersionUID = 4L;

Here the serialVersionUID represents the class version, and we should increment it if the current version of your class is modified such that it is no longer backwards compatible with its previous version.

Serialization-deserialization-demo

2. Java serialization and deserialization example

Lets see an example of how a class is serialized and then deserialized.

package com.howtodoinjava.demo.serialization;

import java.io.*;
import java.util.logging.Logger;
 
public class DemoClass implements java.io.Serializable {
 
	private static final long serialVersionUID = 4L;			//Default serial version uid
	private static final String fileName = "DemoClassBytes.ser"; //Any random name
	private static final Logger logger = Logger.getLogger("");
	//Few data fields
	//Able to serialize
	private static String staticVariable;
	private int intVariable;
	
	//Not able to serialize
	transient private String transientVariable = "this is a transient instance field";
	private Thread threadClass;
	 
	public static void main(String[] args) throws IOException, ClassNotFoundException 
	{
		//Serialization
	
	    DemoClass test = new DemoClass();
	    test.intVariable = 1;
	    staticVariable = "this is a static variable";
	    writeOut(test);
	    System.out.println("DemoClass to be saved: " + test);
	
	    //De-serialization
	    
	    System.out.println("DemoClass deserialized: " + readIn());
	}
	 
	private static Object readIn() throws IOException, ClassNotFoundException {
	    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File(fileName)));
	    return ois.readObject();
	}
	 
	private static void writeOut(java.io.Serializable obj) throws IOException {
	    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File(fileName)));
	    oos.writeObject(obj);
	    oos.close();
	}
	 
	@Override public String toString() {
	    return "DemoClass: final static fileName=" + fileName + ", final static logger=" + logger
	            + ", non-final static staticVariable=" + staticVariable + ", instance intVariable=" + intVariable
	            + ", transient instance transientVariable=" + transientVariable + ", non-serializable instance field threadClass:=" + threadClass;
	}
}

Program Output.

DemoClass to be saved: DemoClass: 
final static fileName=DemoClassBytes.ser, 
final static logger=java.util.logging.LogManager$RootLogger@1d99a4d, 
non-final static staticVariable=this is a static variable, 
instance intVariable=1, 
transient instance transientVariable=this is a transient instance field, 
non-serializable instance field threadClass:=null

//Execute readIn() function from a separate main() method 
//to get given below output correctly. It will flush out the static fields.

DemoClass deserialized: DemoClass: 
final static fileName=DemoClassBytes.ser, 
final static logger=java.util.logging.LogManager$RootLogger@cd2c3c, 
non-final static staticVariable=null, 
instance intVariable=1, 
transient instance transientVariable=null, 
non-serializable instance field threadClass:=null

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class.

3. How to generate serialVersionUID

Joshua Bloch says in Effective Java that the automatically generated UID is generated based on a class name, implemented interfaces, and all public and protected members. Changing any of these in any way will change the serialVersionUID.

However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations and can produce different serialVersionUID in different environments. This can result in unexpected InvalidClassException during deserialization.

Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier in serialVersionUID where possible, since such declarations apply only to the immediately declaring class.

Also note that serialVersionUID field is not useful as inherited member.

Based on my short career, I can say that storing serialized data for a long time span [spatial serialization] is not very common usecase. It is far more common to use the serialization mechanism to temporarily write data [temporal serialization] to for instance a cache or send it over the network to another program to utilize the information.

In such cases, we are not interested in maintaining backwards compatibility. We are only concerned with making sure that the code bases which are communicating on network, indeed have the same version of relevant classes. In order to facilitate such a check, we must maintain the serialVersionUID just as it and don’t change it. Also, do not forget to update it when making incompatible changes to your classes, on both side applications on network.

4. Java classes without serialVersionUID

It is not the situation which we ever want to face. But, it’s reality and sometimes it happen (should i say rarely?). If we need to change such class in incompatible way but want to maintain serialization/deserialization capability with old version of the class, we can use the JDK tool “serialver“. This tool generates the serialVersionUID on the old class, and explicitly set that on the new class. Do not forget to to implement readObject() and writeObject() methods because the built-in deserialization mechanism (in.defaultReadObject()) will refuse to deserialize from old versions of the data.

If we define our own readObject() function which can read back old data. This custom code should check the serialVersionUID in order to know which version the data is in and decide how to deserialize it. This versioning technique is useful if we store serialized data which survives several versions of your code.

Read more : Java serialization compatible and incompatible changes

5. Java serialVersionUID – Summary

  1. transient and static fields are ignored in serialization. After deserialization transient fields and non-final static fields will be null.

    final and static fields still have values since they are part of the class data.

  2. ObjectOutputStream.writeObject(obj) and ObjectInputStream.readObject() are used in serialization and deserialization.
  3. During serialization, we need to handle IOException; during deserialization, we need to handle IOException and ClassNotFoundException. So the deserialized class type must be in the classpath.
  4. Uninitialized non-serializable, non-transient instance fields are tolerated.

    When adding “private Thread th;“, no error in serializable. However, “private Thread threadClass = new Thread();” will cause exception:

    Exception in thread "main" java.io.NotSerializableException: java.lang.Thread
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at com.howtodoinjava.demo.serialization.DemoClass.writeOut(DemoClass.java:42)
    at com.howtodoinjava.demo.serialization.DemoClass.main(DemoClass.java:27)
    
  5. Serialization and deserialization can be used for copying and cloning objects. It is slower than regular clone, but can produce a deep copy very easily.
  6. If I need to serialize a Serializable class Employee, but one of its super classes is not Serializable, can Employee class still be serialized and deserialized? The answer is yes, provided that the non-serializable super-class has a no-arg constructor, which is invoked at deserialization to initialize that super-class.
  7. We must be careful while modifying a class implementing java.io.Serializable. If class does not contain a serialVersionUID field, its serialVersionUID will be automatically generated by the compiler.

    Different compilers, or different versions of the same compiler, will generate potentially different values.

  8. Computation of serialVersionUID is based on not only fields, but also on other aspect of the class like implement clause, constructors, etc. So the best practice is to explicitly declare a serialVersionUID field to maintain backward compatibility. If we need to modify the serializable class substantially and expect it to be incompatible with previous versions, then we need to increment serialVersionUID to avoid mixing different versions.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

25 thoughts on “Java serialVersionUID – How to generate serialVersionUID”

  1. Hi Lokesh,
    When i ran the problem i am getting below output.

    DemoClass to be saved: DemoClass: final static fileName=DemoClassBytes.ser, final static logger=java.util.logging.LogManager$RootLogger@7d4991ad, non-final static staticVariable=this is a static variable, instance intVariable=1, transient instance transientVariable=this is a transient instance field, non-serializable instance field threadClass:=null
    DemoClass deserialized: DemoClass: final static fileName=DemoClassBytes.ser, final static logger=java.util.logging.LogManager$RootLogger@7d4991ad, non-final static staticVariable=this is a static variable, instance intVariable=1, transient instance transientVariable=null, non-serializable instance field threadClass:=null

    After running this problem I am getting non-final static fields will not be null.

    Can you please elaborate.

    Reply
    • Yes. static variables are the part of class so on deserialization, Static variable value will be loaded with current value defined in the class.
      The result mentioned in the example is wrong and need to be corrected.

      Reply
    • I assume because the serialVersionUID is not serialized but the class is. Also its not required to serialize the serialVersionUID. Its just for the JVM to uniquely identify the class during deserialization.

      Reply
  2. Hi Lokesh,

    What is the difference whether we use default serial version UID i.e private static final long serialVersionUID = 1L; or generated serial version UID (using IDE e.g eclipse or IntelliJ)

    -Manoj

    Reply
    • Serial version id is used while de-serialization. If they don’t match, de-serialization fails. If its generated, then changing class structure will change the serial version id as well. You can assume them as version number for classes.

      Reply
      • My question was that if i decide to have the serialVersionUID field in the class not let the JVM generate it.
        There are two ways.

        1) private static final long serialVersionUID = 1L;
        Give 1,2 ,3 etc numbers

        2) Generate it through eclipse one time.

        So what is the difference between these two aproaches? de-serialization will still pass in both the cases but is there any problem we have it 1L always?

        Suppose other classes and for all classes I give 1L , will it make any difference?

        Reply
  3. Hi Lokesh,

    You stated that static fields can not be serialized. But i can get the static field data after deserialization.

    public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;
    String Name;
    static int age = 11;

    Employee(String n) {
    this.Name = n;
    }

    }

    public class SerializableTest {

    public static void main(String[] args) throws IOException, ClassNotFoundException {

    Employee e1 = new Employee(“Sunil”);
    FileOutputStream fp = new FileOutputStream(“employee.ser”);

    ObjectOutputStream op = new ObjectOutputStream(fp);
    op.writeObject(e1);
    System.out.println(“—————serialization done”);

    FileInputStream fs = new FileInputStream(“employee.ser”);
    ObjectInputStream os = new ObjectInputStream(fs);
    Employee e2 = (Employee)os.readObject();
    System.out.println(“———————-deserialization done \n”);
    System.out.println(“data after deserialization is”+ e2.Name + “—-“+ e2.age);
    }
    }

    Let me know if i am missing anything.
    Thanks,
    Sunil.

    Reply
    • Hi Sunil,

      You are assigning the value of age during instance creation (initialized with it). So, when de-serilization happens; it first creates a blank object (age is set at this stage only); and now serialized values are read and overwritten on field of Employee instance.

      To further clear the concept, I have modified your program and divided the serialization/de-serialization process into two methods. Please run the code into two steps. In first step, comment out the method call “deserializeEmployee()” inside main method. And in second step, comment out the method “serializeEmployee()”, so that fresh object is built using serialized data.

      I have removed the static initialization from Employee class, and writing to it when I am serializing the Employee class only. If it was serialized then I must get it back during deserialization, BUT i do not.

      public class SerializableTest 
      {
      	public static void main(String[] args) throws IOException, ClassNotFoundException {
      		//serializeEmployee();
      		deserializeEmployee();
      	}
      	
      	@SuppressWarnings("resource")
      	private static void serializeEmployee() throws IOException, ClassNotFoundException 
      	{
      		Employee e1 = new Employee("Sunil");
      		
      		//Modified the static value before writing it to employee.ser
      		e1.age = 31;
      		
      		FileOutputStream fp = new FileOutputStream("employee.ser");
      		ObjectOutputStream op = new ObjectOutputStream(fp);
      		op.writeObject(e1);
      		System.out.println("—————serialization done");
      		System.out.println("data after serialization is + —-" + e1.age);
      	}
      
      	@SuppressWarnings("resource")
      	private static void deserializeEmployee() throws IOException, ClassNotFoundException
      	{
      		FileInputStream fs = new FileInputStream("employee.ser");
      		ObjectInputStream os = new ObjectInputStream(fs);
      		Employee e2 = (Employee) os.readObject();
      		System.out.println("———————-deserialization done n");
      		System.out.println("data after deserialization is + —-" + e2.age);
      	}
      }
      
      class Employee implements Serializable 
      {
      	private static final long serialVersionUID = 1L;
      	String Name;
      	static int age = 0;
      	Employee(String n) {
      		this.Name = n;
      	}
      }
      
      Reply
  4. Hi Lokesh,

    “If I need to serialize a Serializable class Employee, but one of its super classes is not Serializable, can Employee class still be serialized and de-serialized? The answer is yes, provided that the non-serializable super-class has a no-arg constructor, which is invoked at de-serialization to initialize that super-class.”

    In one of my business use case i need to implement the reverse of the above quoted line i.e. serializing the super class “Employee” using the subclass object “Manager”, but unfortunately i didn’t find any way for doing it, as by default the subclass object also get serialized.

    So is there any way of serializing only the super class using your subclass ref without change the structure of the subclass.?

    Reply
      • Hi Lokesh,
        thx for the replay, Can you please explain how the Externalization is different from Serialization, i mean from the doc readExternal() and writeExternal() allows more control over the field then the readObject() and writeObject() but the same flexibility can be achieve once you customized the Serialization and implement your logic inside read/writeObject(). so where is the key difference then ?

        Reply
        • Basically, the difference between Serializable and Externalizable is on default capabilities. Classes which implement Serializable, the serialization of the object is taken care of automatically, while classes that implement Externalizable is responsible for serializing itself, without the help of default serialization procedures.

          Only the identity of the class of an Externalizable instance is written in the serialization stream and it is the responsibility of the class to save and restore the contents of its instances. The writeExternal and readExternal methods of the Externalizable interface are implemented by a class to give the class complete control over the format and contents of the stream for an object and its supertypes.

          Reply
  5. U said, non-static fields are not serialized but in the output of the program, I can see “non-final static staticVariable=this is a static variable”? Am I missing something?

    Reply
    • Pretty good observation. The reason that static value was (looked like deserialized) printed because I executed the program in one go (read and write). So the static value was all the time in memory. Though It was not read in de-serialization, though it was pre-set in class, so got printed.
      Anyway, I put a comment in program so that next person do not confuse.
      Thanks for pointing it out.

      Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.