Serializable interface exists in java.io package and forms core of
java serialization mechanism. It doesn't have any method and also called Marker Interface in java. Whenever your class implements java.io.Serializable interface
it becomes Serializable in Java and gives compiler an indication that use Java
Serialization mechanism to serialize this object. Now JVM handle the
searialization process. If your class have readObject and writeObject method JVM
call this methods else it use default implementation. Both methods are (and
must be) declared private, proving that neither method is inherited and
overridden or overloaded. The trick here is that the virtual machine will
automatically check to see if either method is declared during the
corresponding method call. The virtual machine can call private methods of your
class whenever it wants but no other objects can. While serialization JVM generate
SerialVersionUID if it is not available in class.
SerialVersionUID is an ID which is stamped on
object when it get serialized usually hashcode of object, you can use tool serialver to
see serialVersionUID of a serialized
object . SerialVersionUID is used for version control of object. you can
specify serialVersionUID in your class file also. Consequence of
not specifying serialVersionUID is that when you add or modify any field in
class then already serialized class will not be able to recover because
serialVersionUID generated for new class and for old serialized object will be
different. Java serialization process relies on correct serialVersionUID for
recovering state of serialized object and throws java.io.InvalidClassException in case of
serialVersionUID mismatch. Some changes are compatible and others are
incompatible.
Compatible Changes
- Adding fields - When the class being reconstituted has a field that
does not occur in the stream, that field in the object will be initialized
to the default value for its type. If class-specific initialization is
needed, the class may provide a readObject method that can initialize the
field to nondefault values.
- Adding
classes - The stream will contain the type hierarchy of each
object in the stream. Comparing this hierarchy in the stream with the
current class can detect additional classes. Since there is no information
in the stream from which to initialize the object, the class's fields will
be initialized to the default values.
- Removing
classes - Comparing the class hierarchy in the stream with that
of the current class can detect that a class has been deleted. In this
case, the fields and objects corresponding to that class are read from the
stream. Primitive fields are discarded, but the objects referenced by the
deleted class are created, since they may be referred to later in the
stream. They will be garbage-collected when the stream is
garbage-collected or reset.
- Adding writeObject/readObject methods - If the version reading the stream has these methods
then readObject is
expected, as usual, to read the required data written to the stream by the
default serialization. It should call defaultReadObject first
before reading any optional data. The writeObject method is
expected as usual to call defaultWriteObject to write
the required data and then may write optional data.
- Removing writeObject/readObject methods - If the class reading the stream does not have these
methods, the required data will be read by default serialization, and the
optional data will be discarded.
- Adding java.io.Serializable - This is equivalent to adding types. There will be no
values in the stream for this class so its fields will be initialized to
default values. The support for subclassing nonserializable classes
requires that the class's supertype have a no-arg constructor and the
class itself will be initialized to default values. If the no-arg
constructor is not available, theInvalidClassException is
thrown.
- Changing
the access to a field - The access modifiers public, package, protected, and
private have no effect on the ability of serialization to assign values to
the fields.
- Changing
a field from static to nonstatic or transient to nontransient - When
relying on default serialization to compute the serializable fields, this
change is equivalent to adding a field to the class. The new field will be
written to the stream but earlier classes will ignore the value since
serialization will not assign values to static or transient fields.
Incompatible Changes
- Deleting
fields - If a field is deleted in a class, the stream written
will not contain its value. When the stream is read by an earlier class,
the value of the field will be set to the default value because no value
is available in the stream. However, this default value may adversely
impair the ability of the earlier version to fulfill its contract.
- Moving
classes up or down the hierarchy - This cannot be allowed
since the data in the stream appears in the wrong sequence.
- Changing
a nonstatic field to static or a nontransient field to transient - When
relying on default serialization, this change is equivalent to deleting a
field from the class. This version of the class will not write that data
to the stream, so it will not be available to be read by earlier versions
of the class. As when deleting a field, the field of the earlier version
will be initialized to the default value, which can cause the class to
fail in unexpected ways.
- Changing
the declared type of a primitive field - Each version of the class
writes the data with its declared type. Earlier versions of the class
attempting to read the field will fail because the type of the data in the
stream does not match the type of the field.
- Changing
the writeObject or readObject method
so that it no longer writes or reads the default field data or changing it
so that it attempts to write it or read it when the previous version did
not. The default field data must consistently either appear or not appear
in the stream.
- Changing
a class from Serializable to Externalizable or
vice versa is an incompatible change since the stream will contain data
that is incompatible with the implementation of the available class.
- Changing
a class from a non-enum type to an enum type or vice
versa since the stream will contain data that is incompatible with the
implementation of the available class.
- Removing
either Serializable or Externalizable is
an incompatible change since when written it will no longer supply the
fields needed by older versions of the class.
- Adding
the writeReplace or readResolve method
to a class is incompatible if the behavior would produce an object that is
incompatible with any older version of the class.
Java keeps track
of the objects that have been written to the stream, and subsequent instances
are written as an ID, not an actual serialized object.
So,
for your example, if you write instance "a" to the stream, the stream
gives that object a unique ID (let's say "1"). As part of the
serialization of "a", you have to serialize "b", and the
stream gives it another id ("2"). If you then write "b" to
the stream, the only thing that is written is the ID, not the actual object.
The
input stream does the same thing in reverse: for each object that it reads from
the stream, it assigns an ID number using the same algorithm as the output
stream, and that ID number references the object instance in a map. When it
sees an object that was serialized using an ID, it retrieves the original
instance from the map.
This is how the API docs describe
it:
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
This behavior can
cause problems: because the stream holds a hard reference to each object (so
that it knows when to substitute the ID), you can run out of memory if you
write a lot of transient objects to the stream. You solve that by calling reset().
While serialization we need to take care below
points.
- If Collaborator (Fields) is not implementing Serializable it will throw java.io.NotSerializableException, Whether you have no argument constructor or not you will get exception. (To avoid use transient or static)
- If parent is not Serializable and it have no argument or default constructor it will not complain but parent class value will be set initial or default.
- If parent class have argument constructor then it will throw exception. You need to implement Serializable.
Kindly provide your valuable feedback in comment box.
No comments:
Post a Comment