How Deserialization Process Happen in Java?

In one of my previous post related to “Implementing Serializable interface in java“, Mr. Bitoo asked a good question “at the time of the deserializtion, how the JVM creates the object without calling the constructor??“. I thought of replying him in same post in a comment, but in another moment I thought of this a very interesting topic which requires a separate detailed article, as well as discussion with you folks. So, here I am starting the discussion with my limited knowledge in this topic and I will encourage you all to put your thoughts/queries so make this topic clear for all of us. Here I begin.

We have already covered many things related to serialization in java, and some stuff related to deserialization in java as well. I will not again re-iterate the same thing again and directly come to main discussion topic i.e. how deserialization works in Java?

Deserialization is the process by which the object previously serialized is reconstructed back into it’s original form i.e. object instance. The input to the deserialization process is the stream of bytes which we get over the other end of network OR we simply read it from file system/database. One question arise immediately, what is written inside this stream of bytes?

Read More: Mini guide for implementing serializable interface

To be very precise, this stream of bytes (or say serialized data) has all the information about the instance which was serialized by serialization process. This information includes class’s meta data, type information of instance fields and values of instance fields as well. This same information is needed when object is re-constructed back to a new object instance. While deserializing an object, the JVM reads its class metadata from the stream of bytes which specifies whether the class of an object implements either ‘Serializable’ or ‘Externalizable’ interface.

Please note that for the deserialization to happen seamlessly, the bytecode of a class, whose object is being deserialized, must be present within the JVM performing deserialization. Otherwise, the ‘ClassNotFoundException’ is thrown. Isn’t it too obvious ??

If instance implements the serializable interface, then an instance of the class is created without invoking it’s any constructor. Really? then how the object is created if not constructor is called?

Let’s look at the bytecode of a simple eprogram:

public class SimpleProgram
{
    public static void main(String[] args)
    {
        System.out.println("Hello World!");
    }
}

Byte code:

public class SimpleProgram extends java.lang.Object{
public SimpleProgram();
  Code:
   0:	aload_0
   1:	invokespecial	#1; //Method java/lang/Object."":()V
   4:	return

public static void main(java.lang.String[]);
  Code:
   0:	getstatic	#2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:	ldc	#3; //String Hello World!
   5:	invokevirtual	#4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:	return
}

Above bytecode looks real stuff, isn’t it? In our first line, we’re going to push a value from the “local variable table” onto the stack. In this case, we’re really only pushing the implicit reference to “this” so it isn’t the most exciting instruction. Second instruction is main thing. It actually invokes the constructor of super most class and in above case it is Object.java. And once the constructor of super most class (i.e. Object in this case) has been called, rest of the code does specific instructions written in code.

Matching to above concept i.e. constructor of super most class, we have similar concept in deserialization. In deserialization process, it is required that all the parent classes of instance should be Serializable; and if any super class in hirarchy is not Serializable then it must have a default constructor. Now it make sense. So, while deserialization the super most class is searched first until any non-serializable class is found. If all super classes are serializable then JVM end up reaching Object class itself and create an instance of Object class first. If in between searching the super classes, any class is found non-serializable then it’s default constructor will be used to allocate an instance in memory.

If any super class of instance to be de-serialized in non-serializable and also does not have a default constructor then the ‘NotSerializableException‘ is thrown by JVM.

Also, before continuing with the object reconstruction, the JVM checks to see if the serialVersionUID mentioned in the byte stream matches the serialVersionUID of the class of that object. If it does not match then the ‘InvalidClassException‘ is thrown.

Read More: SerialVersionUID in java and related fast facts

So till now we got the instance located in memory using one of superclass’s default constructor. Note that after this no constructor will be called for any class. After executing super class constructor, JVM read the byte stream and use instance’s meta data to set type information and other meta information of instance.

After the blank instance is created, JVM first set it’s static fields and then invokes the default readObject() method [if it’s not overridden, otherwise overridden method will be called] internally which is responsible for setting the values from byte stream to blank instance.

Read More: Example code for readObject() and writeObject()

After the readObject() method is completed, the deserialization process is done and you are ready to work with new deserialized instance.

Please post your thoughts/views/queries for this topic in comments area. These are more than welcome.

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.

31 thoughts on “How Deserialization Process Happen in Java?”

  1. Hi,

    I tried creating super class with no default constructor and non-serializable, still my child class deserialize successfully. Can you please explain, how this happen.

    You mention :-

    “In deserialization process, it is required that all the parent classes of instance should be Serializable; and if any super class in hirarchy is not Serializable then it must have a default constructor. Now it make sense. So, while deserialization the super most class is searched first until any non-serializable class is found. If all super classes are serializable then JVM end up reaching Object class itself and create an instance of Object class first. If in between searching the super classes, any class is found non-serializable then it’s default constructor will be used to allocate an instance in memory.”

    Regards,
    Sumant

    Reply
  2. Hi,

    I tried creating a super class with no default constructor and non-serializable, still I was able to deserialize my child class. Conyou please explain, how is this hapens?

    Reply
  3. First I would like to appreciate for this nice article and for your nice explanation. I have one doubt regarding how the serial version ids are compared.
    You said,
    “Also, before continuing with the object reconstruction, the JVM checks to see if the serialVersionUID mentioned in the byte stream matches the serialVersionUID of the class of that object. If it does not match then the ‘InvalidClassException‘ is thrown.”
    In the byte stream we have serial version id, assuming i am explicitly mentioned. But it is compared with what?. Does the JVM generate the id even though i already specified while deserialization. I am bit confused there. Could you please explain me, how the serial version ids are compared?

    Reply
  4. Hello
    What about Externalizable.when we creat a class that implements Externalizable we must define a no-arg constructor for this class.
    But Externalizable interface implements serializable interface.
    and we know that if a class is serializable its no-arg constructor is not needed to deserialization.then what is the usage of no-arg constructor in Externalizable?
    Thanks

    Reply
  5. Hi Lokesh,

    After reading your article about “How Deserialization Process Happen in Java”, I get confused or you can say get more thoughts to think about deserialization process.

    As per your statements about deserialization process:
    1. Without calling the constructor all deserialization process happens with the help of “metadata exists in byte code”.
    2. While deserialization the super most class is searched first until any non-serializable class is found. If all super classes are serializable then JVM end up reaching Object class itself and create an instance of Object class first.

    So in above two statements one says not calling the constructor and one says calling of super class constructor which not implements serializable. This is only my confusion point.

    After reading this article many times, line by line, below is my understanding about deserialization process.
    Let assume there is a class Test implements Serializable

    For Test class during Deserializtion proces below steps happens.
    Step 1. Super most constructor(not this class constructor as it implements Seriaziable) gets called which not implements serializable. For above class i.e Object class.
    Step 2. And in that reference all values(instance variable value) get omitted for class A from bytecode(metadata).

    Sample Code snippet which I assume which does by JVM, for above two steps will be like this.

    Step 1. Object obj = new Object();
    Step 2. Test test = (Test) obj;
    Step 3. // Values get omitted from byte code into "test" object.
    

    Please validate it and put your thoughts about my understanding.

    Thanks

    Reply
  6. If any super class of instance to be de-serialized in non-serializable and also does not have a default constructor then the ‘NotSerializableException‘ is thrown by JVM.

    This is wrong.. Even In above scenario we are getting InvalidClassException only . plz cehck once..

    Reply
  7. in java multiple components are distributed across networks and systems.I want to know what exact the components gets distributed in a enterprise applicaion

    Reply
  8. Hi Lokesh,
    If any class in the inheritance hierarchy is non-serializable then exception non-serializable exception is thrown itself so it does not wait for default presence default constructor to b present .Am i right. second because deserialization is the process to resurrect the object state in the form in which it was saved, so logic says that there is no need to execuete any constructor otherwise it will b entirely new state of object instead of the object which we want to resurrect

    Reply
    • Sorry i mean not in Hierarchy ,but when a class is having a reference of other class and that class if not serializable then we get compile time Exception.

      Reply
  9. “Also, before continuing with the object reconstruction, the JVM checks to see if the serialVersionUID mentioned in the byte stream matches the serialVersionUID of the class of that object. If it does not match then the ‘InvalidClassException‘ is thrown.”

    This is fine that serialVersionUID in the byte stream but my doubt is how JVM find “serialVersionUID of the class of the object ” at the time of deserialization as we are sending byte stream over the network only.

    Reply
  10. Suppose I have a map with Serializable object as its value like this.
    Case 1. public final Map extensions = new HashMap();

    On the other hand I have
    Case 2. public final Map extensions
    and this object in the constructor of the class is initialized like this
    extensions = new HashMap();
    Not 100% sure. Do you think the 2 approaches will have different affect or are they same.

    Reply
  11. If we have overridden one of method from ObjectInputStream class e.g. readResolve() then at which point of execution will it going to call during deserialization ?

    Reply
  12. class a{
    a(){sysout(“Hello”)}
    }
    class b extends a implements Serializable{
    }
    during de-serialization,it does not call a() constructor.but what do you mean by having this constructor and its use.

    Reply
  13. “After the blank instance is created, JVM first set it’s static fields and then invokes the default readObject() method [if it’s not overridden, otherwise overridden method will be called] internally which is responsible for setting the values from byte stream to blank instance.”

    How come the static fields are set, when we say that static fields are not serialized?

    Reply
    • Very good question. As static fields are at class level and not at instance level; and if available in runtime, these static fields are verified and refer the value same as other instances available in runtime. De-serialization starts when JVM start copying values inside readObject() method.

      Reply
  14. class A{}
    class B extends A implements Serializable{}
    class C extends B{}

    My question is , whether A should implement Serializable interface, as B is implementing it?

    Reply
    • During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable. The fields of serializable subclasses will be restored from the stream.

      Serialization exception is only thrown if the class being serialized is not serializable. having non-serializable parents is fine (as long as they have a no-arg constructor). Object itself isnt Serializable, and everything extends it.

      Reply
  15. So as you said “while deserialization the super most class is searched first until any non-serializable class is found” it means first non serializable parent’s default constructor called by jvm to construct the object.
    But returned object is instance of parent. how do we get actual child object after this call??? still confused.

    Reply
    • Above process just creates a blank object in memory, as it is the first step even in normal object’s creation. After this, JVM reads meta data information (and field values) from de-serialized data/stream and copy/set it to the new blank instance it created in first step. This meta data holds the information about the actual instance type, and all other parent hirarchy as well.

      Reply
      • But blank object in memory is of parent type and de-serialized data/stream is of actual object type. It means jvm copying the childs stream data into blank parent object. then there must be loss of child data. question still in mind is how suddenly parent object converted into child ref ?? How blank object knows about all the fields child object has ? there can be various type of childs available ??

        Reply
        • It’s all written as metadata. In JVM runtime as well, objects are differentiated based on their metadata information only. JVM maintains and understand this metadata. Using this metadata, JVM is able to identify about actual type of instance.

          Reply
  16. Thanks for the reply,
    I would like to know,For an object there will be a unique hashcode.
    In some cases, If i have an hashcode stored, Will I get a Object?

    Reply
  17. Suppose the server is in US and i’m a user in india. So if some data or object from server is serialized and send on my machine. But i don’t have java/jre/jvm on my machine(nor java enabled browser). In this case how will the object or data de-serialization happen on my machine or will it not happen.So exactly who will do deserialization ?

    Reply
    • In your case de-serialization will not happen. Responsibility of deserialization completely lies with JVM. If you don’t have JVM (read JRE) than you can’t deserialize the class. Period.

      Reply

Leave a Comment

HowToDoInJava

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