Serialization in java – How it works?

Java Serialization

Object serialization is the ability of the object to save a complete copy of it and any other objects that it references to an output stream (external file); so that the object can be recreated from the serialized copy at a later time as and when required.

Java object serialization, introduced as a part of new feature set of Java Development Kit 1.1, provides a feature to transform a group or a single object into a stream of bits, or array of bytes for storing or sending over the network as such so the above said stream of bits or array of bytes can be transformed back into the Java objects. Mostly all of this happens automatically because of the ObjectInputStream and ObjectOutputStream classes. The programmer can choose to implement this function by implementing the Serializable interface while creating the class.

The process of serialization is also known as deflating or marshalling an object, and de-serialization is known as inflating or un-marshalling.

Serialization is the mechanism that provides the ability to an object to write a copy of it and all the other objects it references in an external file through the ObjecctOutputStream class. It can write data structures, graphs, Jframes, or any object irrespective of its type. While serializing the object retains its information on what type of object it is as because while de-serializing this information comes into play to recreate the exact type of object it was.

Thus serialization provides the following benefits:

  • A system for persisting object, i.e.; writing their properties on external files or disk, or saving them to a database.
  • A system for remote procedure calls.
  • A system for distributing objects, for example in software components like COM, COBRA.
  • A system for identifying changes in time varying data.

To entirely understand the concept of serialization one must have a clear understanding of the Object Persistence and Streams. Here we will explain a bit of each just so to remind us of them. Explaining them each would take a separate chapter in itself.








Streams:

Every program needs to write its data to a place or channel, every program needs to read data from a channel as well. In Java these channels from where a program writes or reads it data are known as Stream.

The figure below shows what just has been said about Streams.

Serialization

Graphical representation of Stream

Streams are of two types basically:

  • Byte Stream—Classes named (*Streams)
  • Character Stream—Classes named (*Reader and *Writer)

Every stream that has the ability to write data contains a set of write methods. And every stream that can read data from any source has a similar set of read methods. Once the stream is created all these methods must be invoked.

Now let’s talk about Persistence.








Persistence:

Object Persistence is the ability of objects living or surviving across application runs. What it means is that any object when created during runtime is collected by the JVM garbage collection when that object is no longer in use. But if persistence API is used then that object is not collected by JVM instead is allowed to live and can be accessed the next time the application is run. In other words persistence means having the lifetime of the object independent of the lifetime of the application in which it is running.

One way to implement persistence is to store the object somewhere in an external file or database and retrieve them at a later time. This is where serialization comes into play. Any non-persisted object exists as long as the Java Virtual Machine is running.

Serialized objects are nothing but objects converted into Streams and sent over to files or through network for storage and retrieval.

Implementing the Serializable interface

Any class must implement java.io.Serializable interface for the objects of that class to be serializable.  The Serializable interface has no methods and only acts as a marker to identify the class considered for serialization. Only the fields of the object that has been serialized are preserved, methods or constructors are not preserved as part of the serialized stream.  If any object act as a reference to another object, then that object’s fields are also serialized if that object’s class has been marked Serializable. In other word the object graph is serialized completely. The object graph includes the tree or structure of the field of the object and its sub objects.








The two main classes that help implementing Serializable interface are:

  • ObjectInputStream
  • ObjectOutputStream

Listing 1: A Sample Class to show serialization

[code]
import java.io.*;

public class RandomClass implements Serializable {

// Generate a random value

private static int r() {

return (int)(Math.random() * 10);

}

private int data[];

// Constructor

public RandomClass() {

datafile = new int[r()];

for (int i=0; i<datafile.length; i++)

datafile[i]=r();

}

public void printout() {

System.out.println(“This RandomClass has “+datafile.length+” random integers”);

for (int i=0; i<datafile.length; i++) {

System.out.print(datafile[i]+”:”);

System.out.println();

}

}
[/code]

The above code is used to create a class that is serializable as it is marked by the serializable interface. The class produces a set of random integers when its instance is created.

Listing 2: Sample showing serializing objects out

This code below shows the functionality of writing objects to a stream using the ObjectOutputStream class. The program has an array of integers but to serialize we don’t have to loop through its inner objects. The serializable interface takes care of that automatically.

[code]

import java.io.*;

import java.util.*;

public class OutSerialize {

public static void main (String args[]) throws IOException {

RandomClass rc1 = new RandomClass();

RandomClass rc2 = new RandomClass();

//create a stream chain with object stream at the top.

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(“objects.dat”));

Date now = new Date(System.currentTimeMillis());

//java.util.* was imported for the Date function.

out.writeObject(now);

out.writeObject(rc1);

out.writeObject(rc2);

out.close();

System.out.println(“I have written:”);

System.out.println(“A Date object: “+now);

System.out.println(“Two Group of randoms”);

rc1.printout();

rc2.printout();

}

}

[/code]

Listing 3: Reading serialized object or De-Serialization

This code below demonstrates the functionality of ObjectInputStream Class that reads Serialized data from an external file into the program. Note that the objects have been read in exactly the same order as it was when being written.

[code]

import java.io.*;

import java.util.*;

public class InSerialize {

public static void main (String args[]) throws  IOException, ClassNotFoundException {

ObjectInputStream in =  new ObjectInputStream (new FileInputStream(“objects.dat”));

Date d1 = (Date)in.readObject();

RandomClass rc1 = (RandomClass)in.readObject();

RandomClass rc2 = (RandomClass)in.readObject();

System.out.println(“I have read:”);

System.out.println(“A Date object: “+d1);

System.out.println(“Two Group of randoms”);

rc1.printout();

rc2.printout();

}

}

[/code]

Almost all classes in java are Serilaizable, including the AWT class. A frame, which is a window, contains a set of graphical components. If a frame is serialized, the serialization mechanism takes care and serializes all its components and data (position, contents etc). Some object classes in java cannot be serialized as because they contain data that references transient operating system resources. E.g.  java.io.FileInputStream and java.lang.Thread classes. The entire serialization operation fails if an object contains reference to a non-serializable element, and a NotSerializableException is thrown. If any object contains reference to a non serializable object reference, it can still be serialized by using the transient keyword.

Listing 4: Making objects serializable using ‘transient’ keyword

[code]

public class Sclass implements Serializable{

public transient Thread newThread;

//remember that thread by default is not a serializable class

private String studentID;

private int sum;

}

[/code]

Security in Serialization

Serializing a Class in java implies sending all its data to an external file or database, through a stream. We may sometime want to restrict the data that is serialized.

Two ways of doing it:

  • Either explicitly declare the data we DON’T want to serialize as transient,(by default all data is serialized)
  • Or explicitly declare the data we DO want to serialize by using Externalizable tag.(by default nothing is serialized)

If any data field is marked transient then that field will not be serialized when ObjectOutputStream class is called on that object. E.g. private transient String password;

On the other hand to explicitly declare the data as serializable we need to mark the object as Externalizable, and implement the writeExternal and readExternal methods to write and read data explicitly.








Conclusion:

The object serialization feature is used in many distributed systems as a method of communicating data. But Serialization exposes private details thus breaking the identity of the abstract data type, which may in turn violate encapsulation. Also it is nice to know that data in the serialized object is same as the data written in the original object itself. It is always a good practice to implement the ObjectInputValidation interface and overriding the validateObject() method even if it uses a few more lines of code. If the object is not found to be proper we can throw the InvalidObjectException.

Tagged on: ,
============================================= ============================================== Buy best TechAlpine Books on Amazon
============================================== ---------------------------------------------------------------- electrician ct chestnutelectric
error

Enjoy this blog? Please spread the word :)

Follow by Email
LinkedIn
LinkedIn
Share