HowToDoInJava

  • Python
  • Java
  • Spring Boot
  • Dark Mode
Home / Java / Serialization / Java serialVersionUID – How to generate serialVersionUID

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?

Let us know if you liked the post. That’s the only way we can improve.
TwitterFacebookLinkedInRedditPocket

About Lokesh Gupta

A family guy with fun loving nature. Love computers, programming and solving everyday problems. Find me on Facebook and Twitter.

Feedback, Discussion and Comments

  1. Naman

    June 10, 2018

    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.

    • Akhil Garg

      March 1, 2020

      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.

  2. Ajay Kumar

    June 29, 2017

    static field do not serialize then why we make SerialVersionUDI static?

    • Prashant Choudhary

      November 23, 2019

      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.

  3. Manoj

    November 7, 2016

    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

    • Lokesh Gupta

      November 8, 2016

      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.

      • Manoj Tyagi

        November 8, 2016

        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?

  4. Nirav Shah

    September 4, 2014

    Really good explanation !!

  5. Sunil Kumar

    July 16, 2014

    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.

    • Lokesh Gupta

      July 16, 2014

      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;
      	}
      }
      
  6. HIMANSU NAYAK

    May 3, 2014

    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.?

    • Lokesh Gupta

      May 3, 2014

      Mark all fields in Manager class “transient”. It will prevent the subclass fields to serialize and still you have the same structure.

      • HIMANSU NAYAK

        May 3, 2014

        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 ?

        • Lokesh Gupta

          May 4, 2014

          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.

      • HIMANSU NAYAK

        May 4, 2014

        Hi Lokesh,
        i too have the similar thought on this, hope along with the javadoc in near future Oracle may release the doc with reason behind the design 🙂

  7. Prashant

    March 25, 2014

    detail information about serialization.

  8. Deepesh

    December 6, 2013

    Very detailed explanation specially the Fast Facts.. Thanks for sharing and increasing the readers’ knowledge here..

  9. Atmprakash Sharma

    October 28, 2013

    really good. it contains all the thing in serilization. I want to know serlizable iterface is marker interface. so ,how jvm works with this marker interface, as of in marker interface no, method.

    • Lokesh Gupta

      October 28, 2013

      Using instanceof operator.

      • atmprakash Sharma

        October 28, 2013

        can you show me the code or api.

        • Lokesh Gupta

          October 28, 2013

          Regarding which concept?

  10. Prashant Kumar

    October 21, 2013

    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?

    • Lokesh Gupta

      October 21, 2013

      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.

  11. tofek khan

    October 17, 2013

    good info lokesh, its really helpful for all Java Lovers

  12. Sandeep Patel

    October 16, 2013

    Very good information keep it up !!!

Comments are closed on this article!

Search Tutorials

Java Serialization Tutorial

  • Serialization – Serializable Interface
  • Serialization – SerialVersionUID
  • Serialization – Externalizable
  • Externalizable vs Serializable
  • Serialization – Java Object to XML
  • Serialization – Deserialization Process
  • Serialization – ReadObject and WriteObject
  • Serialization – Deep Cloning using In-memory Serialization

Java Tutorial

  • Java Introduction
  • Java Keywords
  • Java Flow Control
  • Java OOP
  • Java Inner Class
  • Java String
  • Java Enum
  • Java Collections
  • Java ArrayList
  • Java HashMap
  • Java Array
  • Java Sort
  • Java Clone
  • Java Date Time
  • Java Concurrency
  • Java Generics
  • Java Serialization
  • Java Input Output
  • Java New I/O
  • Java Exceptions
  • Java Annotations
  • Java Reflection
  • Java Garbage collection
  • Java JDBC
  • Java Security
  • Java Regex
  • Java Servlets
  • Java XML
  • Java Puzzles
  • Java Examples
  • Java Libraries
  • Java Resources
  • Java 14
  • Java 12
  • Java 11
  • Java 10
  • Java 9
  • Java 8
  • Java 7

Meta Links

  • About Me
  • Contact Us
  • Privacy policy
  • Advertise
  • Guest and Sponsored Posts

Recommended Reading

  • 10 Life Lessons
  • Secure Hash Algorithms
  • How Web Servers work?
  • How Java I/O Works Internally?
  • Best Way to Learn Java
  • Java Best Practices Guide
  • Microservices Tutorial
  • REST API Tutorial
  • How to Start New Blog

Copyright © 2020 · HowToDoInjava.com · All Rights Reserved. | Sitemap

  • Sealed Classes and Interfaces