Skip to main content

Serialization In Java - A Complete Guide

This post is aimed to explain the concept of serialization in depth taking into account all the ins and outs that are required to be known to a Java Developer.

Basic Usage And Information :

Serialization is a very powerful JAVA instrument aimed at saving only the state of a object not its behaviour. This can be used to exchange objects between different systems and networks as is the case in typical enterprise applications.In a way,we can say that we want the object to exist beyond the lifetime of a JVM.


Serialization Mechanism :

This involves basically below steps :
  1. Firstly the metadata related to serializable instance is written which includes name of class,length of class, number of fields,serialversionuid etc.
  2. This metadata is written recursively for superclass if any till it reaches to java.lang.Object superclass. This is helpful when deserializing the class.
  3. Once metadata is written, the actual data is written. This time it begins from superclass to main class.

Implementing Serialization in JAVA :

In order for a class to implement serialization it must implement java.io.Serializable Interface. Serializable is a marker interface which does not have any methods of its own. It is just used to give an indication to JVM that this class needs to handled specially and serialization mechanism needs to be applied on it. 
We will show this with the help of a class SerializableStudent which has two properties id and name that reflect the state of this class.
Serializable Class

You must be curious about the field serialversionUID that is present in the class .We will be discussing the main use of this later on in the post . For now , you can keep in mind that it is used to maintain versioning of class.

Since we had made the 
SerializableStudent eligible for serialization by implementing java.io.Serializable Interface, now comes actual task to serialize the object of this class. For this following method of ObjectOutputStream is used:
public final void writeObject(Object obj)
                       throws IOException
Similarly for deserialzing the object, following method of ObjectInputStream is used :
public final Object readObject()
                  throws IOException,
               ClassNotFoundException
These methods are used by serialization mechanism whenever we make a class eligible for serialization. This hint is provided to the virtual machine by implementing serializable interface .  We will make use of them in our code as shown :
Test Serialization Main Class


Output: 

Console Output

Code Explanation :

We have created a object of SerializableStudent at line 14. This object will be serialized using method serialize at line 17 which will create file data.ser to save the objects state.The objects state corresponds to its instance variables which in this case is id:1 and name : Student1 . This state along with the class metadata information is saved in data.ser file.
Data File


This is done using method writeObj() of ObjectOutputStream at line 39 .
Now the next step is to deserialize this object from the data.ser file created above . This is done using deserialize method at line 19 which will internally call readObject() method of ObjectInputStream and return the SerializableStudent  object . 
The output of line 20 : Student Id is : 1 Student Name is : Student1 confirms that the same object which has been serialized has been deserialized.


Special Cases :

  1. Static variables do not take part in serialization.This is because static variables are class level variables. They do not belong to any particular object and here in serialization our focus is to save the Object's state.
  2. If you don't want any non-static variable to be saved as part of serialization , then make it as Transient.So when you try to fetch the transient variable from the deserialized object , its default value is returned . 
  3. All the access specifiers like private,public,protected,default are not considered when serializing an object.This means instance variable is serialized irrespective of its access specifier.
  4. During deserialization of object , it's constructor is never called. There is a very interesting logic behind this. As it has been already mentioned in the post that during serialization , the metadata of the class along with that of the superclasses is also saved. So JVM has all the information for constructing this object from the byte stream.The only thing that is required is to allocate memory for this instance which is assigned by calling the constructor of superclass. So the JVM searches for the the first non-serializable superclass and calls its constructor to allocate memory. In case all the parent classes are also serializable , then JVM goes until java.lang.Object class and calls its default constructor.The no-arg constructor of every non-serializable superclass will run when an object is deserialized.
  5. Serialization allows certain amount of class variation such that even after some changes in the class you can deserialize the object without any issues. The operations that are allowed are adding a new field,making a static field to non-static or making a transient field to non-transient. Last two are same like adding a new field in layman's terms. These are called compatible changes. But the opposite operations i.e deletion of some field is not allowed . This is because if we allow deletion then how will you obtain the deleted field from the original serialized object.These are called incompatible changes.
Since we have got the understanding of serialization mechanism, its usage ,implementation and special cases, we should also look into the deeper side of this . I have written a follow up post for this which can give you deeper insight. You can refer :https://easeurtechnology.blogspot.com/2018/02/deeper-insight-into-java-serialization.html

Comments

Post a Comment

Popular posts from this blog

Java Constructors

Constructor as the name suggests is used to construct something and here in case of JAVA it is used to construct the object of class. This is the first point where the object is assigned memory in heap and its member variables gets initialized by default values.Whenever we create an object by using new() keyword,it internally gives call to the default constructor of class. Even if you don't declare the default constructor , java compiler provides automatically a default constructor. Let us test this out with a example . We have created a java class Student.java with a test class TestConstructor.java as shown below  : Student.java TestConstructor.java Here we have created a object of Student class at line 9 using new keyword. This gives call to the default constructor of Student class. Note that we have not defined the default constructor explicitly in Student.java . This is provided by java compiler internally. The equivalent code that java compiler provides is as bel

Deeper Insight Into Java Serialization

Sometimes when a object is serialized at one server and deserialized at other server i.e on different JVMs , deserialization may fall and you can come across  InvalidClassException . This seems to be quite weird. Right? This post is aimed at explaining the root cause of this issue and what should be the better approach while implementing  serialization . You can refer to my other blog on Serialization where we have learnt the serialization mechanism and how to implement serialization  in Java to get started on  serialization. Basically , when we serialize any object , the class metadata is also saved along with object's state which is used while that object is deserialized. One thing that is part of this metadata is  serialVersionUID . In my previous post , I told you that it is used for versioning. We will now see what does it actually mean . You must have seen that whenever you implement serializable interface , compiler gives you warning to generate  serialVersionUID( suid )