The writeObject method is used to serialize an object to the stream. An object is serialized as follows:
1. If a subclass is overriding the implementation, call the writeObjectOverride method and return. Overriding the implementation is described at the end of this section.
2. If there is data in the block-data buffer, the data is written to the stream and the buffer is reset.
3. If the object is null, null is put in the stream and writeObject returns.
4. If the object has been previously replaced, as described in Step 8, write the handle of the replacement to the stream and writeObject returns.
5. If the object has already been written to the stream, its handle is written to the stream and writeObject returns.
6. If the object is a Class, the corresponding ObjectStreamClass is written to the stream, a handle is assigned for the class, and writeObject returns.
7. If the object is an ObjectStreamClass, a handle is assigned to the object, after which it is written to the stream using one of the class descriptor formats described in section 4.3. In versions 1.3 and later of the Java 2 SDK, Standard Edition, the writeClassDescriptor method is called to output the ObjectStreamClass if it represents a class that is not a dynamic proxy class, as determined by passing the associated Class object to the isProxyClass method of java.lang.reflect.Proxy. Afterwards, an annotation for the represented class is written: if the class is a dynamic proxy class, then the annotateProxyClass method is called; otherwise, the annotateClass method is called. The writeObject method then returns.
8. Process potential substitutions by the class of the object and/or by a subclass of ObjectInputStream.
a. If the class of an object is not an enum type and defines the appropriate writeReplace method, the method is called. Optionally, it can return a substitute object to be serialized.
b. Then, if enabled by calling the enableReplaceObject method, the replaceObject method is called to allow subclasses of ObjectOutputStream to substitute for the object being serialized. If the original object was replaced in the previous step, the replaceObject 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.
9. If the object is a java.lang.String, the string is written as length information followed by the contents of the string encoded in modified UTF-8. For details, refer to Section 6.2, "Stream Elements". A handle is assigned to the string, and writeObject returns.
10. If the object is an array, writeObject is called recursively to write the ObjectStreamClass 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 which writeObject returns.
11. If the object is an enum constant, the ObjectStreamClass for the enum type of the constant is written by recursively calling writeObject. It will appear in the stream only the first time it is referenced. A handle is assigned for the enum constant. Next, the value returned by the name method of the enum constant is written as a String object, as described in step 9. Note that if the same name string has appeared previously in the stream, a back reference to it will be written. The writeObject method then returns.
12. 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 the object.
13. The contents of the object are written to the stream.
a. 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, the defaultWriteObject method is called to write the serializable fields to the stream. If the class does have a writeObject method, it is called. It may call defaultWriteObject or putFields and writeFields to save the state of the object, and then it can write other information to the stream.
b. If the object is externalizable, the writeExternal method of the object is called.
c. If the object is neither serializable or externalizable, the NotSerializableException is thrown.