Sunday, February 7, 2016

Serialization vs Externalization

Serialization vs Externalization

In case of Serializable Java Virtual machine has full control for serializing object while in case of Externalizable, application gets control for persisting objects. writeExternal() and readExternal() method provides complete control on format and content of Serialization process to application which can be leverage to increase performance and speed of serialization process.

1. In case of Serializable, default serialization process is used  while in case of Externalizable custom Serialization process is used which is implemented by application. The Java runtime will use reflection to figure out how to marshal and unmarshal your objects.

2. JVM gives call back to  readExternel() and writeExternal() of java.io.Externalizalbe interface for restoring and writing objects into persistence.

3. Externalizable interface provides complete control of serialization process to application.

4. readExternal() and writeExternal() supersede any specific implementation of writeObject and readObject methods.

Reasons why Serialization results in performance issues :

1) Serialization is a recursive algorithm. What I mean to say here is, apart from the fields that are required, starting from a single object, until all the objects that can be reached from that object by following instance variables, are also serialized. Obviously this slows down the performance.

2) Both serializing and deserializing require the serialization mechanism to discover information about the instance it is serializing. Using the default serialization mechanism, will use reflection to discover all the field values. Also the information about class description is added to the stream which includes the descption of all the serializable superclasses, the description of the class and the instance data associated with the specific instance of the class. Lots of data and metadata and again performance issue.

3) You know that serialization needs serialVersionUID, a unique Id to identify the information persisted. If you dont explicitly set a serialiVersionUID, serialization will compute the serialiVersionUID by going through all the fields and methods. So based on the size of the class, again serialization mechanism takes respective amount of time to calculate the value. A third performance issue.

Externalization

Unlike Serializable interface,  Externalizable interface is not a marker interface and it provides two methods - writeExternal and readExternal.

How serialization happens?

JVM first checks for the Externalizable interface and if object supports Externalizable interface, then serializes the object using writeExternal method. If the object does not support Externalizable but implement Serializable, then the object is saved using ObjectOutputStream. Now when an Externalizable object is reconstructed, an instance is created first using the public no-arg constructor, then the readExternal method is called. Again if the object does not support Externalizable, then Serializable objects are restored by reading them from an ObjectInputStream.

a) When only Child class is Externalize

public class RunExternalization {

      public static void main(String[] args) throws IOException,
                  ClassNotFoundException {
            Car car = new Car("Go Nxt","Air Bags","Datsun", 24);
            Car newCar = null;
            /*
             * Serialize the car object.. JVM checks whether class implements
             * Serializable or Externalization if Externalization interface,                         then calls writeExternal and readExternal() methods.
             */

            FileOutputStream fo = new FileOutputStream("car.ser");
            ObjectOutputStream os = new ObjectOutputStream(fo);
            os.writeObject(car);
            fo.close();
            os.close();

            /*
             * Deserialize the car object... When an Externalizable object is
             * reconstructed, an instance is created using the public no-arg
             * constructor, then the readExternal method called. Serializable
             * objects are restored by reading them from an ObjectInputStream.
             */

            FileInputStream fi = new FileInputStream("car.ser");
            ObjectInputStream oi = new ObjectInputStream(fi);
            newCar = (Car) oi.readObject();
            oi.close();

            System.out.println("The original car is ");
            System.out.println(car);
            System.out.println("The new car is ");
            System.out.println(newCar);
      }
}

class Vehicle {
      String model;
      String features;

      public Vehicle() {
      }

      public Vehicle(String model, String features) {
            this.model = model;
            this.features = features;
      }
}

class Car extends Vehicle implements Externalizable {

      String name;
      int year;

      // mandatory public no-arg constructor..
      public Car() {
      }
     
      public Car(String model,String features,String name,int year){
            this.model=model;
            this.features=features;
            this.name=name;
            this.year=year;
      }
      public Car(String name, int year) {
            this.name = name;
            this.year = year;
      }

      /*
       * The object implements the writeExternal method to save its contents by calling the methods of DataOutput for its primitive values or calling the
       * writeObject method of ObjectOutput for objects, strings and arrays
       */

      public void writeExternal(ObjectOutput out) throws IOException {
            out.writeObject(model);
            out.writeObject(features);
           
            out.writeObject(name);
            out.writeInt(year);
      }

      /*
       * The readExternal method must read the values in the same sequence and with the same types as were written by writeExternal
       */

      public void readExternal(ObjectInput in) throws IOException,
                  ClassNotFoundException {
            model=(String) in.readObject();
            features=(String) in.readObject();
           
            name = (String) in.readObject();
            year = in.readInt();
      }

      public String toString() {
            return ("Model no:"+model+"\n Features:"+ features+"\n Name: " + name + "\n" + "Year: " + year);
      }
}

Output :

The original car is
Model no:Go Nxt
 Features:Air Bags
 Name: Datsun
Year: 24
The new car is
Model no:Go Nxt
 Features:Air Bags
 Name: Datsun
Year: 24

b) When both Parent and Child class are Externalized

class Vehiclee implements Externalizable {
      String model;
      String features;

      public Vehiclee() {
      }

      public Vehiclee(String model, String features) {
            this.model = model;
            this.features = features;
      }

      public void writeExternal(ObjectOutput out) throws IOException {
            out.writeObject(model);
            out.writeObject(features);
      }

      public void readExternal(ObjectInput in) throws IOException,
                  ClassNotFoundException {
            model = (String) in.readObject();
            features = (String) in.readObject();
      }
}

class Carr extends Vehiclee implements Externalizable {

      String name;
      int year;

      // mandatory public no-arg constructor..
      public Carr() {
      }

      public Carr(String name, int year) {
            this.name = name;
            this.year = year;
      }

      /*
       * The object implements the writeExternal method to save its contents by calling the methods of DataOutput for its primitive values or calling the
       * writeObject method of ObjectOutput for objects, strings and arrays
       */

      public void writeExternal(ObjectOutput out) throws IOException {
            /* first we call the writeExternal of the superclass as to write
               all the superclass data fields*/
            super.writeExternal(out);
            out.writeObject(name);
            out.writeInt(year);
      }

      /*
       * The readExternal method must read the values in the same sequence and with the same types as were written by writeExternal
       */

      public void readExternal(ObjectInput in) throws IOException,
                  ClassNotFoundException {
            super.readExternal(in);
            name = (String) in.readObject();
            year = in.readInt();
      }

      public String toString() {
            return ("Model no:" + model + "\n Features:" + features + "\n Name: "
                        + name + "\n" + "Year: " + year);
      }
}

public class ParentChildExternalizable {

}


No comments:

Post a Comment