Monday, 18 February 2019

Serialization


To Serialize an object means, to convert its state to a byte stream (which can be moved over a network, persisted on a file drive, persisted in a Data base) so that the byte stream can be reverted back into a copy of the object. A Java object is Serializable  if its class or any of its superclasses implements the Serializable interface or its subinterface i.e. the Externalizable.

Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. 

The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.
The default serialization mechanism for an object writes 

  • the class of the object
  • the class signature
  • the values of all non-transient and non-static fields - this includes references to other objects (except in transient or static fields) to be written also (only if they are implementing Serializable interface or its subinterface)

Multiple references to a single object are encoded using a reference sharing mechanism so that graphs of objects can be restored to the same shape as when the original was written. 

Deserialization is the process of converting the serialized form of an object back into a copy of the object.

 What if a class implements Serializable but it's parent class does not?


  • To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime.
  • During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable. The fields of serializable subclasses will be restored from the stream.
NOTEWhen traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.


When an object is serialized, information that identifies its class is recorded in the serialized stream. However, the class's definition ("class file") itself is not recorded. It is the responsibility of the system that is deserializing the object to determine how to locate and load the necessary class files. 

What if I want don't want Java to handle Serialization?


The Java platform specifies a default way by which serializable objects are serialized. A (Java) class can override this default serialization and define its own way of serializing objects of that class. The Object Serialization Specification describes object serialization in detail.

Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures: 
  • private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {}
  • private void writeObject(java.io.ObjectOutputStream stream) throws IOException {}
  • private void readObjectNoData() throws ObjectStreamException {}

DataOutput Interface


The DataOutput interface provides for converting data from any of the Java primitive types to a series of bytes and writing these bytes to a binary stream. There is also a facility for converting a String into modified UTF-8 format and writing the resulting series of bytes.
For all the methods in this interface that write bytes, it is generally true that if a byte cannot be written for any reason, an IOException is thrown.

There is something known as serialVersionUID; What is it? When to use it? How to use it?

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:
 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.

Examples demonstrating all the concepts of Serialization have been commited the below githib repo

https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/serialization

No comments:

Post a Comment

Volatile keyword, Synchronized keyword and Lock interface

Volatile Marking a member variable as volatile, makes sure, when ever the member variable is accessed, its value is always read from the...