The following are enhancements to serialization in version
1.4 of the Java 2 Platform. For a summary of enhancements
in previous releases, see Enhancements
in Previous Releases.
Support for deserialization of unshared objects
Serialization now provides extra support for deserialization of
objects which are known to be unshared in the data-serialization
stream. The new support is provided by the following API additions
in package java.io:
Previously, security-conscious programmers had to clone private internal
objects after deserializing them to guard against the possibility that
outside parties with access to the serialization stream could append
spurious back handles to the sensitive objects, resulting in extra
references to them during deserialization. However, this solution slows
performance and wastes memory -- two objects must be created and a copy
operation invoked in order to ensure a unique reference to a single usable
object. The new API additions provide a more efficient solution by
allowing receivers to invalidate "unshared" objects as they are read in,
making it impossible for third parties to dereference back-handles to those
objects occurring later in the stream.
Security permissions now required to override putFields, readFields
These changes will not affect the great majority of applications.
However, it will affect any ObjectInputStream/ObjectOutputStream
subclasses which override the putFields or readFields
methods without also overriding the rest of the serialization infrastructure.
Support for class-defined readObjectNoData method
In addition to supporting class-defined writeObject()
and readObject()
methods, serialization now includes support for class-defined
readObjectNoData() methods. Each class-defined
readObjectNoData() method is required to have
the following signature:
The readObjectNoData() method is analogous to the class-defined
readObject() method, except that (if defined) it is called in
cases where the class descriptor for a superclass of the object being
deserialized (and hence the object data described by that class descriptor)
is not present in the serialization stream. More formally:
If object O of class C is being deserialized, and S is a superclass of C
in the VM which is deserializing O, then S.readObjectNoData()
is invoked by ObjectInputStream during the deserialization of O if
and only if the following conditions are true:
S implements java.io.Serializable (directly or indirectly).
S defines an readObjectNoData() method with
the signature listed above.
The serialization stream containing O does not include a class
descriptor for S among its list of superclass descriptors for C.
Note that readObjectNoData() is never invoked in cases
where a class-defined readObject() method could be called,
though serializable class implementors can call
readObjectNoData() from within readObject() as a
means of consolidating initialization code.
See the class description in the API specification of ObjectInputStream for more information.
Bug fix: Deserialization fails for Class object of primitive type
In previous releases, bug 4171142 caused attempts
to deserialize Class objects of primitive types to fail with a
ClassNotFoundException. The problem was that
ObjectInputStream.resolveClass() did not work for
ObjectStreamClass descriptors for primitive types. This bug
is fixed in J2SE 1.4.0.
Bug fix: ObjectInputStream.resolveProxyClass can fail for non-public
interface cases
In previous releases, ObjectInputStream.resolveProxyClass would not always
select the proper class loader to define the proxy class in if one or more
of the proxy interfaces were non-public. In this release,
if ObjectInputStream.resolveProxyClass detects a non-public interface, it
attempts to define the implementing proxy class in the same class loader as
the interface (barring conflicts, in which case an exception is thrown),
which is necessary in order for the proxy to implement the interface.
Bug fix: Invalid serialPersistentFields field name causes
NullPointerException
In previous releases, bug 4387368 caused NullPointerExceptions to be thrown
when serializing objects which used default serialization but also declared
serialPersistentField entries which did not map to actual class fields.
Serialization will now throw InvalidClassExceptions in such cases (since it
is never necessary to define such "unbacked" serialPersistentFields when
using default serialization).
Bug fix: ClassNotFoundException in skipped objects causes
serialization to fail
In previous releases, ClassNotFoundExceptions triggered by "skipped"
objects--objects associated with fields not present in the classes loaded
by the deserializing party--would cause deserialization of the entire
object graph to fail, even though the skipped values would not be included
in the graph. This release of serialization addresses this problem by
ignoring ClassNotFoundExceptions associated with such skipped objects, thus
eliminating a class of unnecessary deserialization errors. Other
miscellaneous changes have also been made to improve the overall robustness
of serialization with regards to ClassNotFoundExceptions encountered during
deserialization.