- Serialization is a Marker interface -Marker Interface is used by java runtime engine (JVM) to identify the class for special processing.
- Serialization does not store Transient or any Static variable that associated with class rather than object.
- Primary purpose of java serialization is to write an object into a stream, so that it can be transported through a network and that object can be rebuilt again.
- When there are two different parties involved, you need a protocol to rebuild the exact same object again.
- Java serialization API just provides you that.
- Other ways you can leverage the feature of serialization is you can use it to perform a deep copy.
- serialization mechanism has been added into the Java language for two reasons:
- The JavaBeans mechanism uses serialization for storing objects into flat file or when application runs in multiple JVM (JVM clustering for performance) it helps beans to move across JVMs over network.
- Remote method invocation (RMI) allows you to automatically use objects located at another host in the network just like any local objects.
- serialVersionUID is used to ensure that “during de-serialization the same class that was used during serialize process is loaded.
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
- SerialVersionUID is a static final field. we can assign any number of your choice to it.
- serialVersionUID is a must in serialization process. But it is optional for the developer to add it in java source file.
- If you are not going to add it in java source file, serialization runtime will generate a serialVersionUID and associate it with the class.
- The serialized object will contain this serialVersionUID along with other data.
- Even though serialVersionUID is a static field, it gets serialized along with the object.
- This is one exception to the general serialization rule that, “static fields are not serialized”.
How serialVersionUID is generated:
- serialVersionUID is a 64-bit hash of the class name, interface class names, methods and fields. Serialization runtime generates a serialVersionUID if you do not add one in source.
- Secure Hash Algorithm (SHA-1) is used to compute a signature for the stream. The first two 32-bit quantities are used to form a 64-bit hash.
- It is advised to have serialVersionUID as unique as possible. That’s why the java runtime chose to have such a complex algorithm to generate it.
How serialVersionUID works?
- When an object is serialized, the serialVersionUID is serialized along with the other contents.
- Later when that is deserialized, the serialVersionUID from the deserialized object is extracted and compared with the serialVersionUID of the loaded class.
- If the numbers do not match then, InvalidClassException is thrown.
- If the loaded class is not having a serialVersionUID declared, then it is automatically generated using the same algorithm as before.
- serialVersionUID should be maintained. As and when you change anything in the class, you should upgrade the serailVersionUID. Try your best to declare a unique serialVersionUID.
Limitations of Serialization:
- File size is very high.
- Customization due to transient which is not effective because we get “null” in place of transient attributes.
- While customizing we also get a meta-information of the file which includes when created who are eligible to read it etc: which is against data security.
In order to address these limitations of serialization, sun people came up with another I/O process named Externalization, which refers to dumping the state of an object in a permanent media using the interface Externalizable.
- Externalizable is a sub-interface to Serializable but it is not a marker interface because it has two unimplemented methods readExternal() and writeExternal() which should be implemented by the classes which use Externalizable interface.
- Externalization is same as serialization except that WriteObject() and ReadObject() method are called by JVM during sterilization an de-serialization of object.
- One thing you can do with Externalization is that you can store extra information into object like STATIC variables and transient variables or you can add more information if you have any business need.
- One good example is compressing and uncompressing of data to send it through network or converting one format to other like a BMP image to JPEG or GIF format.
Performance issue –
- Further more if you are sub classing your externalizable class you will want to invoke your super class’s implementation. So this causes overhead while you subclass your externalizable class.
- Methods in externalizable interface are public. So any malicious program can invoke which results into loosing the prior serialized state.
- Customization is very easy incase of externalization because whatever attributes we want to keep away from externalization just don’t keep them inside writeExternal() method block.
- In writeExternal() method block we make attributes externalized by using corresponding methods for different types of data. We should take care of IOException while using this method.
Ex: writeInt(i)———- for integers
writeUTF(s) ——-for strings
writeObject(i) ——- for derived attributes other than string& wrapper classes.
UTF–Universal Text Format
- Using readExternal() method we can read the states of the object returned using the corresponding read methods stated above.
- Flushing and closing operations are same to that of serialization.
- All the rules of derived attributes & Inheritance applied for serialization are also valid in case of Externalization.
- If a class uses any derived attributes other than String & all Wrapper class attributes then that particular class also should be implemented with either Externalizable or Serializable interface.If we don’t do so, we get NotSerializableException.
Advantages of externalization over serialization are:
- File size is highly reduced (nearly 1/3).
- Customization is very easy and more effective.
WriteRepalce() and readResolve():
- writeRepalce(): Serializable classes that need to designate an alternative object to be used when writing an object to the stream should implement this special method with the exact signature:
ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
readResolve(): Classes that need to designate a replacement when an instance of it is read from the stream should implement this special method with the exact signature.
ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
If we create the singleton object by cloning the address of the objects may vary, but the objects are same in terms of properties. Objects address can’t decide that the objects’ equality.