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.
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:
This is done using method writeObj() of ObjectOutputStream at line 39 .
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 :
- Firstly the metadata related to serializable instance is written which includes name of class,length of class, number of fields,serialversionuid etc.
- This metadata is written recursively for superclass if any till it reaches to java.lang.Object superclass. This is helpful when deserializing the class.
- 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 |
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 IOExceptionSimilarly 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 |
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 :
- 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.
- 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 .
- 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.
- 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.
- 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
Nice article Bhavya!
ReplyDeleteThanks. Please do share it.
Delete