CONTENTS | PREV | NEXT | Java Object Serialization Specification |
ClassObjectOutputStream
implements object serialization. It maintains the state of the stream including the set of objects already serialized. Its methods control the traversal of objects to be serialized to save the specified objects and the objects to which they refer.package java.io; public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants { public ObjectOutputStream(OutputStream out) throws IOException; public final void writeObject(Object obj) throws IOException; public void defaultWriteObject(); throws IOException, NotActiveException; public PutField putFields() throws IOException; public writeFields() throws IOException; public void reset() throws IOException; protected void annotateClass(Class cl) throws IOException; protected Object replaceObject(Object obj) throws IOException; protected boolean enableReplaceObject(boolean enable) throws SecurityException; protected void writeStreamHeader() throws IOException; public void write(int data) throws IOException; public void write(byte b[]) throws IOException; public void write(byte b[], int off, int len) throws IOException; public void flush() throws IOException; protected void drain() throws IOException; public void close() throws IOException; public void writeBoolean(boolean data) throws IOException; public void writeByte(int data) throws IOException; public void writeShort(int data) throws IOException; public void writeChar(int data) throws IOException; public void writeInt(int data) throws IOException; public void writeLong(long data) throws IOException; public void writeFloat(float data) throws IOException; public void writeDouble(double data) throws IOException; public void writeBytes(String data) throws IOException; public void writeChars(String data) throws IOException; public void writeUTF(String data) throws IOException; // Inner class to provide access to serializable fields. abstract static public class PutField { public void put(String name, boolean value) throws IOException, IllegalArgumentException; public void put(String name, char data) throws IOException, IllegalArgumentException; public void put(String name, byte data) throws IOException, IllegalArgumentException; public void put(String name, short data) throws IOException, IllegalArgumentException; public void put(String name, int data) throws IOException, IllegalArgumentException; public void put(String name, long data) throws IOException, IllegalArgumentException; public void put(String name, float data) throws IOException, IllegalArgumentException; public void put(String name, double data) throws IOException, IllegalArgumentException; public void put(String name, Object data) throws IOException, IllegalArgumentException; } public void useProtocolVersion(int version) throws IOException; protected ObjectOutputStream() throws IOException; protected writeObjectOverride() throws NotActiveException, IOException; }The
ObjectOutputStream
constructor requires anOutputStream
. The constructor callswriteStreamHeader
to write a magic number and version to the stream, that will be read and verified by the correspondingreadStreamHeader
in theObjectInputStream
constructor.The
writeObject
method is used to serialize an object to the stream. An object is serialized as follows:Exceptions may occur during the traversal or may occur in the underlying stream. For any subclass of
- If a subclass is overriding the implementation, call the
writeObjectOverride
method and return. Overriding the implementation is described at the end of this section.- If there is data in the block-data buffer, the data is written to the stream and the buffer is reset.
- If the object is null, null is put in the stream and
writeObject
returns.- If the object has been previously replaced, as described in Step 8, write the handle of the replacement to the stream and
writeObject
returns.- If the object has already been written to the stream, its handle is written to the stream and
writeObject
returns.- If the object is a
Class
, the correspondingObjectStreamClass
is written to the stream, a handle is assigned for the class, andwriteObject
returns.- If the object is an
ObjectStreamClass
, a descriptor for the class is written to the stream including its name,serialVersionUID
, and the list of fields by name and type. A handle is assigned for the descriptor. TheannotateClass
subclass method is called beforewriteObject
returns.- Process potential substitutions by the class of the object and/or by a subclass of
ObjectInputStream
.
- If the class of an object defines the appropriate
writeReplace
method, the method is called. Optionally, it can return a substitute object to be serialized.- Then, if enabled by calling the
enableReplaceObject
method, thereplaceObject
method is called to allow subclasses ofObjectOutputStream
to substitute for the object being serialized. If the original object was replaced in the previous step, thereplaceObject
method is called with the replacement object.If the original object was replaced by either one or both steps above, the mapping from the original object to the replacement is recorded for later use in Step 4. Then, Steps 3 through 7 are repeated on the new object.
If the replacement object is not one of the types covered by Steps 3 through 7, processing resumes using the replacement object at Step 10.
- If the object is a
java.lang.String,
the string is written in Universal Transfer Format (UTF) format, a handle is assigned to the string, andwriteObject
returns.- If the object is an array,
writeObject
is called recursively to write theObjectStreamClass
of the array. The handle for the array is assigned. It is followed by the length of the array. Each element of the array is then written to the stream, after whichwriteObject
returns.- For regular objects, the
ObjectStreamClass
for the class of the object is written by recursively calling writeObject. It will appear in the stream only the first time it is referenced. A handle is assigned for this object.- The contents of the object is written to the stream.
- If the object is serializable, the highest serializable class is located. For that class, and each derived class, that class's fields are written. If the class does not have a
writeObject
method, thedefaultWriteObject
method is called to write the serializable fields to the stream. If the class does have awriteObject
method, it is called. It may calldefaultWriteObject
orputFields
andwriteFields
to save the state of the object, and then it can write other information to the stream.- If the object is externalizable, the
writeExternal
method of the object is called.- If the object is neither serializable or externalizable, the
NotSerializableException
is thrown.IOException
, the exception is written to the stream using the exception protocol and the stream state is discarded. If a secondIOException
is thrown while attempting to write the first exception into the stream, the stream is left in an unknown state andStreamCorruptedException
is thrown fromwriteObject
. For other exceptions, the stream is aborted and left in an unknown and unusable state.The
defaultWriteObject
method implements the default serialization mechanism for the current class. This method may be called only from a class'swriteObject
method. The method writes all of the serializable fields of the current class to the stream. If called from outside thewriteObject
method, theNotActiveException
is thrown.The
putFields
method returns aPutField
object the caller uses to set the values of the serializable fields in the stream. The fields may be set in any order. After all of the fields have been set,writeFields
must be called to write the field values in the canonical order to the stream. If a field is not set, the default value appropriate for its type will be written to the stream. This method may only be called from within thewriteObject
method of a serializable class. It may not be called more than once or ifdefaultWriteObject
has been called. Only afterwriteFields
has been called can other data be written to the stream.The
reset
method resets the stream state to be the same as if it had just been constructed.Reset
will discard the state of any objects already written to the stream. The current point in the stream is marked as reset, so the correspondingObjectInputStream
will reset at the same point. Objects previously written to the stream will not be remembered as already having been written to the stream. They will be written to the stream again. This is useful when the contents of an object or objects must be sent again.Reset
may not be called while objects are being serialized. If called inappropriately, anIOException
is thrown.The
annotateClass
method is called while aClass
is being serialized, and after the class descriptor has been written to the stream. Subclasses may extend this method and write other information to the stream about the class. This information must be read by theresolveClass
method in a correspondingObjectInputStream
subclass.An
ObjectOutputStream
subclass can implement thereplaceObject
method to monitor or replace objects during serialization. Replacing objects must be enabled explicitly by callingenableReplaceObject
before callingwriteObject
with the first object to be replaced. Once enabled,replaceObject
is called for each object just prior to serializing the object for the first time. Note that thereplaceObject
method is not called for objects of the specially handled classes,Class
andObjectStreamClass
. An implementation of a subclass may return a substitute object that will be serialized instead of the original. The substitute object must be serializable. All references in the stream to the original object will be replaced by the substitute object.When objects are being replaced, the subclass must ensure that the substituted object is compatible with every field where the reference will be stored, or that a complementary substitution will be made during deserialization. Objects, whose type is not a subclass of the type of the field or array element, will later abort the deserialization by raising a
ClassCastException
and the reference will not be stored.The
enableReplaceObject
method can be called by trusted subclasses ofObjectOutputStream
to enable the substitution of one object for another during serialization. Replacing objects is disabled untilenableReplaceObject
is called with atrue
value. It may thereafter be disabled by setting it tofalse
. The previous setting is returned. TheenableReplaceObject
method checks that the stream requesting the replacement can be trusted. To ensure that the private state of objects is not unintentionally exposed, only trusted stream subclasses may usereplaceObject
. Trusted classes are those classes that belong to a security protection domain with permission to enable Serializable substitution.If the subclass of
ObjectOutputStream
is not considered part of the system domain,SerializablePermission "enableSubstitution"
must be added to the security policy file.AccessControlException
is thrown if the protection domain of the subclass ofObjectInputStream
does not have permission to"enableSubstitution"
by callingenableReplaceObject
. See the document JavaTM Security Architecture (JDK1.2) for additional information about the security model.The
writeStreamHeader
method writes the magic number and version to the stream. This information must be read by thereadStreamHeader
method ofObjectInputStream
. Subclasses may need to implement this method to identify the stream's unique format.The
flush
method is used to empty any buffers being held by the stream and to forward the flush to the underlying stream. Thedrain
method may be used by subclassers to empty only theObjectOutputStream
's buffers without forcing the underlying stream to be flushed.All of the write methods for primitive types encode their values using a
DataOutputStream
to put them in the standard stream format. The bytes are buffered into block data records so they can be distinguished from the encoding of objects. This buffering allows primitive data to be skipped if necessary for class versioning. It also allows the stream to be parsed without invoking class-specific methods.To override the implementation of serialization, the subclass of
ObjectOutputStream
should call the protected no-arg
ObjectOutputStream
, constructor. There is a security check within the no-arg constructor forSerializablePermission "enableSubclassImplementation"
to ensure that only trusted classes are allowed to override the default implementation. This constructor does not allocate any private data forObjectOutputStream
and sets a flag that indicates that the finalwriteObject
method should invoke thewriteObjectOverride
method and return. All otherObjectOutputStream
methods are not final and can be directly overridden by the subclass.