This blog will cover following details.
Introduction
Object graphs in Serialization
Customized serialization
Serialization wrt inheritance
Externalization
SerialVersionUID
Introduction
The process of converting an object from java supported form to file/network supported form is called serialization. The process of converting an object from file/network supported form to java supported form is called de-serialization
Java Object is a binary data.
How to implement serialization?
Create Java Object
Create Object output stream -> converts Object data to binary data
File Output stream -> Writes the binary data to file data
import java.io.*;
class Dog implements Serializable{
int i=10;
int j=20;
}
class SerializeDemo{
public static void main(String[] args) throws Exception{
Dog d= new Dog();
FileOutputStream fos=new FileOutputStream("abc.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(d);
FileInputStream fis=new FileInputStream("abc.txt");
ObjectInputStream ois=new ObjectInputStream(fis);
Dog d2=(Dog)ois.readObject();
System.out.println(d2.i + ".. " + d2.j);
}
}
Points to Note:
Serializable interface does not contain any methods. Such interfaces with out any methods are called marker interface.
To serialize an object, the object must be serializable
transient keyword plays important in serialization. It is a modifier and is applicable only for variables. When a variable is marked as transient, jvm ignores original value and save default value to file
Static: static variables are at Class level and not part of Object. They do not participate in serialization.
Final: Every final variable will be replaced with actual value at compile time itself. They will never be available as variable at runtime. They will participate in serialization as value, but will have no impact.
We can serialize any number of objects to a file. De-serialization will happen in the same sequence. If we don't know order of objects in Serialization we can use instanceOf function.
FileInputStream fis=new FileInputStream("abc.txt");
ObjectInputStream ois =new ObjectInputStream(fis);
Object obj=ois.readObject();
if (obj instanceof Dog) {Dog d2=(Dog) obj; }
Object Graphs in Serialization - When an Object is serialized, all Objects which are reachable from that Object will be serilized automatically. This group of objects is nothing bug Object Graph.
In Object Graph, every object should be Serializable. If atleast one object is non serializable then we will get Runtime Exception saying NotSerializableException.
class Dog implements Serializable{
Cat c=new Cat();
}
class Cat implements Serializable{
Rat r= new Rat();
}
class Rat implements Serializable{
int j=20;
}
class SerializedDemo{
public static void main (String[] args) throws Exception{
Dog d1=new Dog();
FOS fos=new FOS("abc.txt"):
OOS oos= new OOS(fos);
oos.writeObject(d1);
FIS fos=new FIS("abc.txt"):
OIS oos= new OIS(fis);
DOG d2=(Dog)ois.readObject();
sop(d2.c.r.j);
}
}
Customized Serialization: In default serialization there may be loss of information due to transient key word. To recover such loss of information we should go for Customized Serialization.
We can implement customized serialization using 2 methods.
private void writeObject(OOS os) throws Exception
private void readObject(OIS is) throws Exception
These methods will be executed implicitly by jvm during serialization/de-serialization. These are called as callback methods.
eg:
class Account implements Serializable{
String un="Venkat";
transient String pwd="password";
private void writeObject(OOS os) throws Exception{
os.defaultWriteObject(); //This is meant to ask jvm to perform default Serialization.
String epwd="()"+pwd;
os.writeObject();
}
private void readObject(OIS is) throws Exception{
is.defaultReadObject(); //This is meant to ask jvm to perform default De-Serialization.
String epwd=(String)is.readObject();
pwd=epwd.substring(2);
}
}
Serialization with respect to Inheritance:
Case1: If parent is Serializable then by Default every child is Serializable.
GenericServlet is serializable. All servlet classes in java by default implements Serializable.
Case2:Child class is marked as serializable where as Parent class is NOT. Points to note:
a) To Serialize Child Class Object, Parent class Neet not be Serialized.
b) At the time of Serialization, jvm will check if any instance variable is inherited from non-Serializable parent. JVM will ignore such variable Original values and save default values to the file.
c) At the time of DeSerialization JVM will check if any Parent class is Non-Serializable. If any Parent class is NonSerializable then JVM will execute instance control flow(identification of instance members) on that non-serializable parent and share its instance variables to the current object.
d) To execute instance control flow execution of Non-Serializable parent JVM will always invoke No Argument Constructor. Hence every non-Serializable class should contain No-Argument Constructor. Else system raises run time exception saying InvalidClassException.
Externalization:
Serialization should be preferred if we want to save complete object. In this case, jvm takes care of complete process.
Externalization should be preferred if we want to save part of the object to file. In this case programmer has complete control.
Externalizable is child interface of Serializable
Serializable is a marker interface. Where as Externalizable has 2 methods. writeExternal() and readExternal()
writeExternal() -> this method will be executed at the time of serialization
readExternal()-> At the time of deserialization, file does not contain complete object. JVM will create separate new object automatically by calling public no argument constructor. On that object JVM will call readExternal() method to read values from file and assign to the object.
Serial Version UID
In serialization both sender and receiver need not be same and need not be from same location and need not use same location. At the time of serialization JVM will save a unique id with every object. This unique id will be generated by jvm based on a .class file. At the time of deserialization Receiver side jvm will compare object unique id with local .class unique id. Deserialization will be performed only when both are matched. Otherwise receiver will fail to deserialize and will get run time exception. The unique id is called Serial Version UID
Points to note: Problems of depending on default Version UID generated by jvm::
Both sender and receiver should use same jvm wrt vendor and version
After serialization if we change .class file at receiver side then we can't perform deserialization because of mismatch in serialVersionUID.
To generate serialVersionUID, internally jvm will use complex algorithm which may create performance problem.
We can solve above problem by configuring our own serialVersionUID as below
private static final long serialVersionUID = 1L;
Introduction
Object graphs in Serialization
Customized serialization
Serialization wrt inheritance
Externalization
SerialVersionUID
Introduction
The process of converting an object from java supported form to file/network supported form is called serialization. The process of converting an object from file/network supported form to java supported form is called de-serialization
Java Object is a binary data.
How to implement serialization?
Create Java Object
Create Object output stream -> converts Object data to binary data
File Output stream -> Writes the binary data to file data
import java.io.*;
class Dog implements Serializable{
int i=10;
int j=20;
}
class SerializeDemo{
public static void main(String[] args) throws Exception{
Dog d= new Dog();
FileOutputStream fos=new FileOutputStream("abc.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(d);
FileInputStream fis=new FileInputStream("abc.txt");
ObjectInputStream ois=new ObjectInputStream(fis);
Dog d2=(Dog)ois.readObject();
System.out.println(d2.i + ".. " + d2.j);
}
}
Points to Note:
Serializable interface does not contain any methods. Such interfaces with out any methods are called marker interface.
To serialize an object, the object must be serializable
transient keyword plays important in serialization. It is a modifier and is applicable only for variables. When a variable is marked as transient, jvm ignores original value and save default value to file
Static: static variables are at Class level and not part of Object. They do not participate in serialization.
Final: Every final variable will be replaced with actual value at compile time itself. They will never be available as variable at runtime. They will participate in serialization as value, but will have no impact.
We can serialize any number of objects to a file. De-serialization will happen in the same sequence. If we don't know order of objects in Serialization we can use instanceOf function.
FileInputStream fis=new FileInputStream("abc.txt");
ObjectInputStream ois =new ObjectInputStream(fis);
Object obj=ois.readObject();
if (obj instanceof Dog) {Dog d2=(Dog) obj; }
Object Graphs in Serialization - When an Object is serialized, all Objects which are reachable from that Object will be serilized automatically. This group of objects is nothing bug Object Graph.
In Object Graph, every object should be Serializable. If atleast one object is non serializable then we will get Runtime Exception saying NotSerializableException.
class Dog implements Serializable{
Cat c=new Cat();
}
class Cat implements Serializable{
Rat r= new Rat();
}
class Rat implements Serializable{
int j=20;
}
class SerializedDemo{
public static void main (String[] args) throws Exception{
Dog d1=new Dog();
FOS fos=new FOS("abc.txt"):
OOS oos= new OOS(fos);
oos.writeObject(d1);
FIS fos=new FIS("abc.txt"):
OIS oos= new OIS(fis);
DOG d2=(Dog)ois.readObject();
sop(d2.c.r.j);
}
}
Customized Serialization: In default serialization there may be loss of information due to transient key word. To recover such loss of information we should go for Customized Serialization.
We can implement customized serialization using 2 methods.
private void writeObject(OOS os) throws Exception
private void readObject(OIS is) throws Exception
These methods will be executed implicitly by jvm during serialization/de-serialization. These are called as callback methods.
eg:
class Account implements Serializable{
String un="Venkat";
transient String pwd="password";
private void writeObject(OOS os) throws Exception{
os.defaultWriteObject(); //This is meant to ask jvm to perform default Serialization.
String epwd="()"+pwd;
os.writeObject();
}
private void readObject(OIS is) throws Exception{
is.defaultReadObject(); //This is meant to ask jvm to perform default De-Serialization.
String epwd=(String)is.readObject();
pwd=epwd.substring(2);
}
}
Serialization with respect to Inheritance:
Case1: If parent is Serializable then by Default every child is Serializable.
GenericServlet is serializable. All servlet classes in java by default implements Serializable.
Case2:Child class is marked as serializable where as Parent class is NOT. Points to note:
a) To Serialize Child Class Object, Parent class Neet not be Serialized.
b) At the time of Serialization, jvm will check if any instance variable is inherited from non-Serializable parent. JVM will ignore such variable Original values and save default values to the file.
c) At the time of DeSerialization JVM will check if any Parent class is Non-Serializable. If any Parent class is NonSerializable then JVM will execute instance control flow(identification of instance members) on that non-serializable parent and share its instance variables to the current object.
d) To execute instance control flow execution of Non-Serializable parent JVM will always invoke No Argument Constructor. Hence every non-Serializable class should contain No-Argument Constructor. Else system raises run time exception saying InvalidClassException.
Externalization:
Serialization should be preferred if we want to save complete object. In this case, jvm takes care of complete process.
Externalization should be preferred if we want to save part of the object to file. In this case programmer has complete control.
Externalizable is child interface of Serializable
Serializable is a marker interface. Where as Externalizable has 2 methods. writeExternal() and readExternal()
writeExternal() -> this method will be executed at the time of serialization
readExternal()-> At the time of deserialization, file does not contain complete object. JVM will create separate new object automatically by calling public no argument constructor. On that object JVM will call readExternal() method to read values from file and assign to the object.
Serial Version UID
In serialization both sender and receiver need not be same and need not be from same location and need not use same location. At the time of serialization JVM will save a unique id with every object. This unique id will be generated by jvm based on a .class file. At the time of deserialization Receiver side jvm will compare object unique id with local .class unique id. Deserialization will be performed only when both are matched. Otherwise receiver will fail to deserialize and will get run time exception. The unique id is called Serial Version UID
Points to note: Problems of depending on default Version UID generated by jvm::
Both sender and receiver should use same jvm wrt vendor and version
After serialization if we change .class file at receiver side then we can't perform deserialization because of mismatch in serialVersionUID.
To generate serialVersionUID, internally jvm will use complex algorithm which may create performance problem.
We can solve above problem by configuring our own serialVersionUID as below
private static final long serialVersionUID = 1L;


