CONTENTS | PREV | NEXT | Java Object Serialization Specification version 6.0 |
CHAPTER 4 |
TheObjectStreamClass
provides information about classes that are saved in a Serialization stream. The descriptor provides the fully-qualified name of the class and its serialization version UID. ASerialVersionUID
identifies the unique original class version for which this class is capable of writing streams and from which it can read.package java.io; public class ObjectStreamClass { public static ObjectStreamClass lookup(Class cl); public static ObjectStreamClass lookupAny(Class cl); public String getName(); public Class forClass(); public ObjectStreamField[] getFields(); public long getSerialVersionUID(); public String toString(); }Thelookup
method returns theObjectStreamClass
descriptor for the specified class in the virtual machine. If the class has definedserialVersionUID
it is retrieved from the class. If theserialVersionUID
is not defined by the class, it is computed from the definition of the class in the virtual machine. If the specified class is not serializable or externalizable, null is returned.The
lookupAny
method behaves like thelookup
method, except that it returns the descriptor for any class, regardless of whether it implementsSerializable
. TheserialVersionUID
of a class that does not implementSerializable
is 0L.The
getName
method returns the name of the class, in the same format that is used by theClass.getName
method.The
forClass
method returns theClass
in the local virtual machine if one was found byObjectInputStream.resolveClass
method. Otherwise, it returns null.The
getFields
method returns an array ofObjectStreamField
objects that represent the serializable fields of this class.The
getSerialVersionUID
method returns theserialVersionUID
of this class. Refer to Section 4.6, "Stream Unique Identifiers." If not specified by the class, the value returned is a hash computed from the class's name, interfaces, methods, and fields using the Secure Hash Algorithm (SHA) as defined by the National Institute of Standards.The
toString
method returns a printable representation of the class descriptor including the name of the class and theserialVersionUID
.
ObjectStreamClass descriptors are also used to provide information about dynamic proxy classes (e.g., classes obtained via calls to the getProxyClass method of java.lang.reflect.Proxy) saved in a serialization stream. A dynamic proxy class itself has no serializable fields and a serialVersionUID of 0L. In other words, when the Class object for a dynamic proxy class is passed to the static lookup method of ObjectStreamClass, the returned ObjectStreamClass instance will have the following properties:
The serialized form of an ObjectStreamClass instance depends on whether or not the Class object it represents is serializable, externalizable, or a dynamic proxy class.When an
ObjectStreamClass
instance that does not represent a dynamic proxy class is written to the stream, it writes the class name andserialVersionUID
, flags, and the number of fields. Depending on the class, additional information may be written:
- For non-serializable classes, the number of fields is always zero. Neither the
SC_SERIALIZABLE
nor theSC_EXTERNALIZABLE
flag bits are set.- For serializable classes, the
SC_SERIALIZABLE
flag is set, the number of fields counts the number of serializable fields and is followed by a descriptor for each serializable field. The descriptors are written in canonical order. The descriptors for primitive typed fields are written first sorted by field name followed by descriptors for the object typed fields sorted by field name. The names are sorted usingString.compareTo
. For details of the format, refer to Section 6.4, "Grammar for the Stream Format".- For externalizable classes, flags includes the
SC_EXTERNALIZABLE
flag, and the number of fields is always zero.- For enum types, flags includes the
SC_ENUM
flag, and the number of fields is always zero.
When an ObjectOutputStream serializes the ObjectStreamClass descriptor for a dynamic proxy class, as determined by passing its Class object to the isProxyClass method of java.lang.reflect.Proxy, it writes the number of interfaces that the dynamic proxy class implements, followed by the interface names. Interfaces are listed in the order that they are returned by invoking the getInterfaces method on the Class object of the dynamic proxy class.The serialized representations of ObjectStreamClass descriptors for dynamic proxy classes and non-dynamic proxy classes are differentiated through the use of different typecodes (TC_PROXYCLASSDESC and TC_CLASSDESC, respectively); for a more detailed specification of the grammar, see Section 6.4, "Grammar for the Stream Format".
AnObjectStreamField
represents a serializable field of a serializable class. The serializable fields of a class can be retrieved from theObjectStreamClass
.The special static serializable field,
serialPersistentFields
, is an array ofObjectStreamField
components that is used to override the default serializable fields.package java.io; public class ObjectStreamField implements Comparable { public ObjectStreamField(String fieldName, Class fieldType); public ObjectStreamField(String fieldName, Class fieldType, boolean unshared); public String getName(); public Class getType(); public String getTypeString(); public char getTypeCode(); public boolean isPrimitive(); public boolean isUnshared(); public int getOffset(); protected void setOffset(int offset); public int compareTo(Object obj); public String toString(); }ObjectStreamField
objects are used to specify the serializable fields of a class or to describe the fields present in a stream. Its constructors accept arguments describing the field to represent: a string specifying the name of the field, aClass
object specifying the type of the field, and aboolean
flag (implicitlyfalse
for the two-argument constructor) indicating whether or not values of the represented field should be read and written as "unshared" objects if default serialization/deserialization is in use (see the descriptions of theObjectInputStream.readUnshared
andObjectOutputStream.writeUnshared
methods in sections 3.1 and 2.1, respectively).The
getName
method returns the name of the serializable field.The
getType
method returns the type of the field.The
getTypeString
method returns the type signature of the field.The
getTypeCode
method returns a character encoding of the field type (`B'
forbyte
,`C'
forchar
,`D'
fordouble
,`F'
forfloat
,`I'
forint
,`J'
forlong
,`L'
for non-array object types,`S'
forshort
,`Z'
forboolean
, and`[`
for arrays).The
isPrimitive
method returnstrue
if the field is of primitive type, orfalse
otherwise.The
isUnshared
method returnstrue
if values of the field should be written as "unshared" objects, orfalse
otherwise.The
getOffset
method returns the offset of the field's value within instance data of the class defining the field.The
setOffset
method allowsObjectStreamField
subclasses to modify the offset value returned by thegetOffset
method.The
compareTo
method comparesObjectStreamFields
for use in sorting. Primitive fields are ranked as "smaller" than non-primitive fields; fields otherwise equal are ranked alphabetically.The
toString
method returns a printable representation with name and type.
The program serialver can be used to find out if a class is serializable and to get itsserialVersionUID
. When invoked with the-show option, it puts up a simple user interface. To find out if a class is serializable and to find out its serialVersionUID,
enter its full class name, then press either the Enter or the Show button. The string printed can be copied and pasted into the evolved class.
When invoked on the command line with one or more class names, serialver prints theserialVersionUID
for each class in a form suitable for copying into an evolving class. When invoked with no arguments, it prints a usage line.
Each versioned class must identify the original class version for which it is capable of writing streams and from which it can read. For example, a versioned class must declare:private static final long serialVersionUID = 3487495895819393L;The stream-unique identifier is a 64-bit hash of the class name, interface class names, methods, and fields. The value must be declared in all versions of a class except the first. It may be declared in the original class but is not required. The value is fixed for all compatible classes. If the SUID is not declared for a class, the value defaults to the hash for that class. TheserialVersionUID
for dynamic proxy classes and enum types always have the value 0L. Array classes cannot declare an explicitserialVersionUID
, so they always have the default computed value, but the requirement for matchingserialVersionUID
values is waived for array classes.
Note - It is strongly recommended that all serializable classes explicitly declareserialVersionUID
values, since the defaultserialVersionUID
computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpectedserialVersionUID
conflicts during deserialization, causing deserialization to fail.
The initial version of anExternalizable
class must output a stream data format that is extensible in the future. The initial version of the methodreadExternal
has to be able to read the output format of all future versions of the methodwriteExternal
.The
serialVersionUID
is computed using the signature of a stream of bytes that reflect the class definition. The National Institute of Standards and Technology (NIST) 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. Ajava.lang.DataOutputStream
is used to convert primitive data types to a sequence of bytes. The values input to the stream are defined by the JavaTM Virtual Machine (VM) specification for classes. Class modifiers may include theACC_PUBLIC
,ACC_FINAL
,ACC_INTERFACE
, andACC_ABSTRACT
flags; other flags are ignored and do not affectserialVersionUID
computation. Similarly, for field modifiers, only theACC_PUBLIC
,ACC_PRIVATE
,ACC_PROTECTED
,ACC_STATIC
,ACC_FINAL
,ACC_VOLATILE
, andACC_TRANSIENT
flags are used when computingserialVersionUID
values. For constructor and method modifiers, only theACC_PUBLIC
,ACC_PRIVATE
,ACC_PROTECTED
,ACC_STATIC
,ACC_FINAL
,ACC_SYNCHRONIZED
,ACC_NATIVE
,ACC_ABSTRACT
andACC_STRICT
flags are used. Names and descriptors are written in the format used by thejava.io.DataOutputStream.writeUTF
method.The sequence of items in the stream is as follows:
private
static
and private transient
fields:
<clinit>
.
java.lang.reflect.Modifier.STATIC
,
written as a 32-bit integer.
()V
.
private
constructor sorted by method name and signature:
<init>
.
private
method sorted by method name and signature:
DataOutputStream
and produces five 32-bit values sha[0..4]
.
H0 H1 H2 H3 H4
, is in an array of five int
values named sha
, the hash value would be computed as follows:
long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF) << 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) << 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) << 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) << 56;