United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4413615 Use of readClassDescriptor/writeClassDescriptor is overloaded
JDK-4413615 : Use of readClassDescriptor/writeClassDescriptor is overloaded

Details
Type:
Bug
Submit Date:
2001-02-09
Status:
Resolved
Updated Date:
2005-06-06
Project Name:
JDK
Resolved Date:
2005-06-06
Component:
core-libs
OS:
generic
Sub-Component:
java.io:serialization
CPU:
generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.3.0
Fixed Versions:

Related Reports

Sub Tasks

Description

Name: boT120536			Date: 02/08/2001


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

The JDK object streams use the read/writeClassDescriptor methods for two
purposes.  This makes overriding these methods very difficult.

In the most common case these methods are used to describe the class of an
object being serialized.  In this case the class is always Serializable.  This
is important because the only public way to get a ObjectStreamClass is through
ObjectStreamClass.lookup which will only return ObjectStreamClasses for
Serializable classes.  Using this one can then implement a version of
writeClassDescriptor which sends the descriptor in a different way and a
version of readClassDescriptor which receives this information and uses
ObjectStreamClass.lookup to find or create the appropriate descriptor.

There is however a less common use of read/writeClassDescriptor which makes
overriding these methods much more difficult (though not quite impossible, see
workaround below).  When an instance of a Class object is serialized out it is
handled specially and the stream ends up calling read/writeClassDescriptor for
the class of which the Class object represents.  In this case the class may not
be Serializable (the Class object is an instance of java.lang.Class which is
Serializable, but may represent some other class which is not a Serializable).
Because the ObjectOutputStream uses default (package) access methods to
construct the ObjectStreamClass to be written this poses no problem for an
implementation of writeClassDescriptor.  However a custom implementation of
readClassDescriptor has no means of creating an ObjectStreamClass for a class
which is not Serializable.

This all makes the ability to override the read/writeClassDescriptor much less
useful than it would otherwise be.  It also seems to me to be part of a bigger
question about serializing Class objects.  It seems a little strange to allow
this, that is what classloading is for.
(Review ID: 110681) 
======================================================================

                                    

Comments
EVALUATION

The use of class descriptors for describing both the class of a serialized
object, and the class of a serialized (perhaps non-serializable) Class object
itself is rooted in the serialization protocol itself, and is unlikely
to change at this point, if for no reason other than compatibility.

The submitter is correct, however, in discerning that ObjectStreamClass
should provide a lookup() variant that allows application code to obtain
class descriptors for non-serializable classes.  Unfortunately, it's late in
the merlin cycle to add a new API, and a usable (albeit ugly) workaround
exists, so this addition may have to be delayed until a subsequent release.

michael.warres@east 2001-03-26
                                     
2001-03-26
WORK AROUND



Name: boT120536			Date: 02/08/2001


There are two workarouds, niether is pleasant.

1.  Use AccessibleObject and reflection to use the default (package) access
method lookpClassInternal on ObjectStreamClass.  This version of the method
doesn't check to make sure that the descriptor is for a Serializable class
before returning.  This obviously only works if you can set the security policy
to allow the AccessibleObject call to work.

2.  Construct your subclass of ObjectInputStream to have a member variable
which is a subclass of ObjectOutputStream (no, that is not a typo).  Have this
subclassed ObjectOutputStream override writeClassDescriptor in such a way that
it stores away the last class descriptor written to an instance variable of
your ObjectInputStream subclass.  Have the output of this ObjectOutputStream be
written to a NullOutputStream, you don't care about it, you are only concerned
with the class descriptor you get in writeClassDescriptor.

In the readClassDescriptor you use the information sent by writeClassDescriptor
to get your hands on the appropriate class.  Call ObjectStreamClass.lookup with
this class as an argument.  If it returns null then the class is not
Serializable.  Call writeObject() on the ObjectOutputStream described above
passing the class as an argument.  This will cause the ObjectOutputStream to
create an appropriate ObjectStreamClass and pass it in to
writeClassDescriptor.  At this point it can be stored in an instance variable.
When the call to writeObject returns you can return the value of this instance
variable from readClassDescriptor.  Be sure to call reset() on the
ObjectOutputStream before or after each use.
======================================================================
                                     
2004-06-11



Hardware and Software, Engineered to Work Together