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 !!

Leave a Reply

31 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.

Our Blogs

REST API Tutorial