jdk/src/java.base/share/specs/serialization/output.md
changeset 45606 9f69dd961bf3
parent 45605 8d019eee3515
parent 45598 5e0712d61fbc
child 45607 a1fb7c733328
equal deleted inserted replaced
45605:8d019eee3515 45606:9f69dd961bf3
     1 ---
       
     2 # Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
       
     3 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4 #
       
     5 # This code is free software; you can redistribute it and/or modify it
       
     6 # under the terms of the GNU General Public License version 2 only, as
       
     7 # published by the Free Software Foundation.
       
     8 #
       
     9 # This code is distributed in the hope that it will be useful, but WITHOUT
       
    10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12 # version 2 for more details (a copy is included in the LICENSE file that
       
    13 # accompanied this code).
       
    14 #
       
    15 # You should have received a copy of the GNU General Public License version
       
    16 # 2 along with this work; if not, write to the Free Software Foundation,
       
    17 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18 #
       
    19 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20 # or visit www.oracle.com if you need additional information or have any
       
    21 # questions.
       
    22 
       
    23 include-before: '[CONTENTS](index.html) | [PREV](serial-arch.html) | [NEXT](input.html)'
       
    24 include-after: '[CONTENTS](index.html) | [PREV](serial-arch.html) | [NEXT](input.html)'
       
    25 
       
    26 title: 'Java Object Serialization Specification: 2 - Object Output Classes'
       
    27 ---
       
    28 
       
    29 -   [The ObjectOutputStream Class](#the-objectoutputstream-class)
       
    30 -   [The ObjectOutputStream.PutField
       
    31     Class](#the-objectoutputstream.putfield-class)
       
    32 -   [The writeObject Method](#the-writeobject-method)
       
    33 -   [The writeExternal Method](#the-writeexternal-method)
       
    34 -   [The writeReplace Method](#the-writereplace-method)
       
    35 -   [The useProtocolVersion Method](#the-useprotocolversion-method)
       
    36 
       
    37 -------------------------------------------------------------------------------
       
    38 
       
    39 ## 2.1 The ObjectOutputStream Class
       
    40 
       
    41 Class `ObjectOutputStream` implements object serialization. It maintains the
       
    42 state of the stream including the set of objects already serialized. Its
       
    43 methods control the traversal of objects to be serialized to save the specified
       
    44 objects and the objects to which they refer.
       
    45 
       
    46 ```
       
    47 package java.io;
       
    48 
       
    49 public class ObjectOutputStream
       
    50     extends OutputStream
       
    51     implements ObjectOutput, ObjectStreamConstants
       
    52 {
       
    53     public ObjectOutputStream(OutputStream out)
       
    54         throws IOException;
       
    55 
       
    56     public final void writeObject(Object obj)
       
    57         throws IOException;
       
    58 
       
    59     public void writeUnshared(Object obj)
       
    60         throws IOException;
       
    61 
       
    62     public void defaultWriteObject()
       
    63         throws IOException, NotActiveException;
       
    64 
       
    65     public PutField putFields()
       
    66         throws IOException;
       
    67 
       
    68     public writeFields()
       
    69         throws IOException;
       
    70 
       
    71     public void reset() throws IOException;
       
    72 
       
    73     protected void annotateClass(Class cl) throws IOException;
       
    74 
       
    75     protected void writeClassDescriptor(ObjectStreamClass desc)
       
    76         throws IOException;
       
    77 
       
    78     protected Object replaceObject(Object obj) throws IOException;
       
    79 
       
    80     protected boolean enableReplaceObject(boolean enable)
       
    81         throws SecurityException;
       
    82 
       
    83     protected void writeStreamHeader() throws IOException;
       
    84 
       
    85     public void write(int data) throws IOException;
       
    86 
       
    87     public void write(byte b[]) throws IOException;
       
    88 
       
    89     public void write(byte b[], int off, int len) throws IOException;
       
    90 
       
    91     public void flush() throws IOException;
       
    92 
       
    93     protected void drain() throws IOException;
       
    94 
       
    95     public void close() throws IOException;
       
    96 
       
    97     public void writeBoolean(boolean data) throws IOException;
       
    98 
       
    99     public void writeByte(int data) throws IOException;
       
   100 
       
   101     public void writeShort(int data) throws IOException;
       
   102 
       
   103     public void writeChar(int data) throws IOException;
       
   104 
       
   105     public void writeInt(int data) throws IOException;
       
   106 
       
   107     public void writeLong(long data) throws IOException;
       
   108 
       
   109     public void writeFloat(float data) throws IOException;
       
   110 
       
   111     public void writeDouble(double data) throws IOException;
       
   112 
       
   113     public void writeBytes(String data) throws IOException;
       
   114 
       
   115     public void writeChars(String data) throws IOException;
       
   116 
       
   117     public void writeUTF(String data) throws IOException;
       
   118 
       
   119     // Inner class to provide access to serializable fields.
       
   120     abstract static public class PutField
       
   121     {
       
   122         public void put(String name, boolean value)
       
   123             throws IOException, IllegalArgumentException;
       
   124 
       
   125         public void put(String name, char data)
       
   126             throws IOException, IllegalArgumentException;
       
   127 
       
   128         public void put(String name, byte data)
       
   129             throws IOException, IllegalArgumentException;
       
   130 
       
   131         public void put(String name, short data)
       
   132             throws IOException, IllegalArgumentException;
       
   133 
       
   134         public void put(String name, int data)
       
   135             throws IOException, IllegalArgumentException;
       
   136 
       
   137         public void put(String name, long data)
       
   138             throws IOException, IllegalArgumentException;
       
   139 
       
   140         public void put(String name, float data)
       
   141             throws IOException, IllegalArgumentException;
       
   142 
       
   143         public void put(String name, double data)
       
   144             throws IOException, IllegalArgumentException;
       
   145 
       
   146         public void put(String name, Object data)
       
   147             throws IOException, IllegalArgumentException;
       
   148     }
       
   149 
       
   150     public void useProtocolVersion(int version) throws IOException;
       
   151 
       
   152     protected ObjectOutputStream()
       
   153         throws IOException;
       
   154 
       
   155      protected writeObjectOverride()
       
   156         throws NotActiveException, IOException;
       
   157 }
       
   158 ```
       
   159 
       
   160 The single-argument `ObjectOutputStream` constructor creates an
       
   161 `ObjectOutputStream` that serializes objects to the given `OutputStream`. The
       
   162 constructor calls `writeStreamHeader` to write a magic number and version to
       
   163 the stream that will be read and verified by a corresponding call to
       
   164 `readStreamHeader` in the single-argument `ObjectInputStream` constructor. If a
       
   165 security manager is installed, this constructor checks for the
       
   166 `"enableSubclassImplementation"` `SerializablePermission` when invoked directly
       
   167 or indirectly by the constructor of a subclass which overrides the `putFields`
       
   168 and/or `writeUnshared` methods.
       
   169 
       
   170 The `writeObject` method is used to serialize an object to the stream. An
       
   171 object is serialized as follows:
       
   172 
       
   173 1.  If a subclass is overriding the implementation, call the
       
   174     `writeObjectOverride` method and return. Overriding the implementation is
       
   175     described at the end of this section.
       
   176 
       
   177 2.  If there is data in the block-data buffer, the data is written to the
       
   178     stream and the buffer is reset.
       
   179 
       
   180 3.  If the object is null, null is put in the stream and `writeObject` returns.
       
   181 
       
   182 4.  If the object has been previously replaced, as described in Step 8, write
       
   183     the handle of the replacement to the stream and `writeObject` returns.
       
   184 
       
   185 5.  If the object has already been written to the stream, its handle is written
       
   186     to the stream and `writeObject` returns.
       
   187 
       
   188 6.  If the object is a `Class`, the corresponding `ObjectStreamClass` is
       
   189     written to the stream, a handle is assigned for the class, and
       
   190     `writeObject` returns.
       
   191 
       
   192 7.  If the object is an `ObjectStreamClass`, a handle is assigned to the
       
   193     object, after which it is written to the stream using one of the class
       
   194     descriptor formats described in [Section 4.3, "Serialized
       
   195     Form"](class.html#serialized-form). In versions 1.3 and later of the Java 2
       
   196     SDK, Standard Edition, the `writeClassDescriptor` method is called to
       
   197     output the `ObjectStreamClass` if it represents a class that is not a
       
   198     dynamic proxy class, as determined by passing the associated `Class` object
       
   199     to the `isProxyClass` method of `java.lang.reflect.Proxy`. Afterwards, an
       
   200     annotation for the represented class is written: if the class is a dynamic
       
   201     proxy class, then the `annotateProxyClass` method is called; otherwise, the
       
   202     `annotateClass` method is called. The `writeObject` method then returns.
       
   203 
       
   204 8.  Process potential substitutions by the class of the object and/or by a
       
   205     subclass of `ObjectInputStream`.
       
   206 
       
   207     a.  If the class of an object is not an enum type and defines the
       
   208         appropriate `writeReplace` method, the method is called. Optionally, it
       
   209         can return a substitute object to be serialized.
       
   210 
       
   211     b.  Then, if enabled by calling the `enableReplaceObject` method, the
       
   212         `replaceObject` method is called to allow subclasses of
       
   213         `ObjectOutputStream` to substitute for the object being serialized. If
       
   214         the original object was replaced in the previous step, the
       
   215         `replaceObject` method is called with the replacement object.
       
   216 
       
   217     If the original object was replaced by either one or both steps above, the
       
   218     mapping from the original object to the replacement is recorded for later
       
   219     use in Step 4. Then, Steps 3 through 7 are repeated on the new object. 
       
   220 
       
   221     If the replacement object is not one of the types covered by Steps 3
       
   222     through 7, processing resumes using the replacement object at Step 10.
       
   223 
       
   224 9.  <a id="java-lang-string-encoding"></a>
       
   225     If the object is a `java.lang.String,` the string is written as length
       
   226     information followed by the contents of the string encoded in modified
       
   227     UTF-8. For details, refer to [Section 6.2, "Stream
       
   228     Elements"](protocol.html#stream-elements). A handle is assigned to the
       
   229     string, and `writeObject` returns.
       
   230 
       
   231 10. If the object is an array, `writeObject` is called recursively to write the
       
   232     `ObjectStreamClass` of the array. The handle for the array is assigned. It
       
   233     is followed by the length of the array. Each element of the array is then
       
   234     written to the stream, after which `writeObject` returns.
       
   235 
       
   236 11. If the object is an enum constant, the `ObjectStreamClass` for the enum
       
   237     type of the constant is written by recursively calling `writeObject`. It
       
   238     will appear in the stream only the first time it is referenced. A handle is
       
   239     assigned for the enum constant. Next, the value returned by the `name`
       
   240     method of the enum constant is written as a `String` object, as described
       
   241     in step 9. Note that if the same name string has appeared previously in the
       
   242     stream, a back reference to it will be written. The `writeObject` method
       
   243     then returns.
       
   244 
       
   245 12. For regular objects, the `ObjectStreamClass` for the class of the object is
       
   246     written by recursively calling `writeObject`. It will appear in the stream
       
   247     only the first time it is referenced. A handle is assigned for the object.
       
   248 
       
   249 13. The contents of the object are written to the stream.
       
   250 
       
   251     a.  If the object is serializable, the highest serializable class is
       
   252         located. For that class, and each derived class, that class's fields
       
   253         are written. If the class does not have a `writeObject` method, the
       
   254         `defaultWriteObject` method is called to write the serializable fields
       
   255         to the stream. If the class does have a `writeObject` method, it is
       
   256         called. It may call `defaultWriteObject` or `putFields` and
       
   257         `writeFields` to save the state of the object, and then it can write
       
   258         other information to the stream.
       
   259 
       
   260     b.  If the object is externalizable, the `writeExternal` method of the
       
   261         object is called.
       
   262 
       
   263     c.  If the object is neither serializable or externalizable, the
       
   264         `NotSerializableException` is thrown.
       
   265 
       
   266 Exceptions may occur during the traversal or may occur in the underlying
       
   267 stream. For any subclass of `IOException`, the exception is written to the
       
   268 stream using the exception protocol and the stream state is discarded. If a
       
   269 second `IOException` is thrown while attempting to write the first exception
       
   270 into the stream, the stream is left in an unknown state and
       
   271 `StreamCorruptedException` is thrown from `writeObject`. For other exceptions,
       
   272 the stream is aborted and left in an unknown and unusable state.
       
   273 
       
   274 The `writeUnshared` method writes an "unshared" object to the
       
   275 `ObjectOutputStream`. This method is identical to `writeObject`, except that it
       
   276 always writes the given object as a new, unique object in the stream (as
       
   277 opposed to a back-reference pointing to a previously serialized instance).
       
   278 Specifically:
       
   279 
       
   280 -   An object written via `writeUnshared` is always serialized in the same
       
   281     manner as a newly appearing object (an object that has not been written to
       
   282     the stream yet), regardless of whether or not the object has been written
       
   283     previously.
       
   284 
       
   285 -   If `writeObject` is used to write an object that has been previously
       
   286     written with `writeUnshared`, the previous `writeUnshared` operation is
       
   287     treated as if it were a write of a separate object. In other words,
       
   288     `ObjectOutputStream` will never generate back-references to object data
       
   289     written by calls to `writeUnshared`.
       
   290 
       
   291 While writing an object via `writeUnshared` does not in itself guarantee a
       
   292 unique reference to the object when it is deserialized, it allows a single
       
   293 object to be defined multiple times in a stream, so that multiple calls to the
       
   294 `ObjectInputStream.readUnshared` method (see [Section 3.1, "The
       
   295 ObjectInputStream Class"](input.html#the-objectinputstream-class)) by the
       
   296 receiver will not conflict. Note that the rules described above only apply to
       
   297 the base-level object written with `writeUnshared`, and not to any transitively
       
   298 referenced sub-objects in the object graph to be serialized.
       
   299 
       
   300 The `defaultWriteObject` method implements the default serialization mechanism
       
   301 for the current class. This method may be called only from a class's
       
   302 `writeObject` method. The method writes all of the serializable fields of the
       
   303 current class to the stream. If called from outside the `writeObject` method,
       
   304 the `NotActiveException` is thrown.
       
   305 
       
   306 The `putFields` method returns a `PutField` object the caller uses to set the
       
   307 values of the serializable fields in the stream. The fields may be set in any
       
   308 order. After all of the fields have been set, `writeFields` must be called to
       
   309 write the field values in the canonical order to the stream. If a field is not
       
   310 set, the default value appropriate for its type will be written to the stream.
       
   311 This method may only be called from within the `writeObject` method of a
       
   312 serializable class. It may not be called more than once or if
       
   313 `defaultWriteObject` has been called. Only after `writeFields` has been called
       
   314 can other data be written to the stream.
       
   315 
       
   316 The `reset` method resets the stream state to be the same as if it had just
       
   317 been constructed. `Reset` will discard the state of any objects already written
       
   318 to the stream. The current point in the stream is marked as reset, so the
       
   319 corresponding `ObjectInputStream` will reset at the same point. Objects
       
   320 previously written to the stream will not be remembered as already having been
       
   321 written to the stream. They will be written to the stream again. This is useful
       
   322 when the contents of an object or objects must be sent again. `Reset` may not
       
   323 be called while objects are being serialized. If called inappropriately, an
       
   324 `IOException` is thrown.
       
   325 
       
   326 Starting with the Java 2 SDK, Standard Edition, v1.3, the
       
   327 `writeClassDescriptor` method is called when an `ObjectStreamClass` needs to be
       
   328 serialized. `writeClassDescriptor` is responsible for writing a representation
       
   329 of the `ObjectStreamClass` to the serialization stream. Subclasses may override
       
   330 this method to customize the way in which class descriptors are written to the
       
   331 serialization stream. If this method is overridden, then the corresponding
       
   332 `readClassDescriptor` method in `ObjectInputStream` should also be overridden
       
   333 to reconstitute the class descriptor from its custom stream representation. By
       
   334 default, `writeClassDescriptor` writes class descriptors according to the
       
   335 format specified in [Section 6.4, "Grammar for the Stream
       
   336 Format"](protocol.html#grammar-for-the-stream-format). Note that this method
       
   337 will only be called if the `ObjectOutputStream` is not using the old
       
   338 serialization stream format (see [Section 6.3, "Stream Protocol
       
   339 Versions"](protocol.html#stream-protocol-versions)). If the serialization
       
   340 stream is using the old format (`ObjectStreamConstants.PROTOCOL_VERSION_1`),
       
   341 the class descriptor will be written internally in a manner that cannot be
       
   342 overridden or customized.
       
   343 
       
   344 The `annotateClass` method is called while a `Class` is being serialized, and
       
   345 after the class descriptor has been written to the stream. Subclasses may
       
   346 extend this method and write other information to the stream about the class.
       
   347 This information must be read by the `resolveClass` method in a corresponding
       
   348 `ObjectInputStream` subclass.
       
   349 
       
   350 An `ObjectOutputStream` subclass can implement the `replaceObject` method to
       
   351 monitor or replace objects during serialization. Replacing objects must be
       
   352 enabled explicitly by calling `enableReplaceObject` before calling
       
   353 `writeObject` with the first object to be replaced. Once enabled,
       
   354 `replaceObject` is called for each object just prior to serializing the object
       
   355 for the first time. Note that the `replaceObject` method is not called for
       
   356 objects of the specially handled classes, `Class` and `ObjectStreamClass`. An
       
   357 implementation of a subclass may return a substitute object that will be
       
   358 serialized instead of the original. The substitute object must be serializable.
       
   359 All references in the stream to the original object will be replaced by the
       
   360 substitute object.
       
   361 
       
   362 When objects are being replaced, the subclass must ensure that the substituted
       
   363 object is compatible with every field where the reference will be stored, or
       
   364 that a complementary substitution will be made during deserialization. Objects,
       
   365 whose type is not a subclass of the type of the field or array element, will
       
   366 later abort the deserialization by raising a `ClassCastException` and the
       
   367 reference will not be stored.
       
   368 
       
   369 The `enableReplaceObject` method can be called by trusted subclasses of
       
   370 `ObjectOutputStream` to enable the substitution of one object for another
       
   371 during serialization. Replacing objects is disabled until `enableReplaceObject`
       
   372 is called with a `true` value. It may thereafter be disabled by setting it to
       
   373 `false`. The previous setting is returned. The `enableReplaceObject` method
       
   374 checks that the stream requesting the replacement can be trusted. To ensure
       
   375 that the private state of objects is not unintentionally exposed, only trusted
       
   376 stream subclasses may use `replaceObject`. Trusted classes are those classes
       
   377 that belong to a security protection domain with permission to enable
       
   378 Serializable substitution.
       
   379 
       
   380 If the subclass of `ObjectOutputStream` is not considered part of the system
       
   381 domain, `SerializablePermission "enableSubstitution"` must be added to the
       
   382 security policy file. `AccessControlException` is thrown if the protection
       
   383 domain of the subclass of `ObjectInputStream` does not have permission to
       
   384 `"enableSubstitution"` by calling `enableReplaceObject`. See the document Java
       
   385 Security Architecture (JDK1.2) for additional information about the security
       
   386 model.
       
   387 
       
   388 The `writeStreamHeader` method writes the magic number and version to the
       
   389 stream. This information must be read by the `readStreamHeader` method of
       
   390 `ObjectInputStream`. Subclasses may need to implement this method to identify
       
   391 the stream's unique format.
       
   392 
       
   393 The `flush` method is used to empty any buffers being held by the stream and to
       
   394 forward the flush to the underlying stream. The `drain` method may be used by
       
   395 subclassers to empty only the `ObjectOutputStream`'s buffers without forcing
       
   396 the underlying stream to be flushed.
       
   397 
       
   398 All of the write methods for primitive types encode their values using a
       
   399 `DataOutputStream` to put them in the standard stream format. The bytes are
       
   400 buffered into block data records so they can be distinguished from the encoding
       
   401 of objects. This buffering allows primitive data to be skipped if necessary for
       
   402 class versioning. It also allows the stream to be parsed without invoking
       
   403 class-specific methods.
       
   404 
       
   405 To override the implementation of serialization, the subclass of
       
   406 `ObjectOutputStream` should call the protected no-arg `ObjectOutputStream`,
       
   407 constructor. There is a security check within the no-arg constructor for
       
   408 `SerializablePermission "enableSubclassImplementation"` to ensure that only
       
   409 trusted classes are allowed to override the default implementation. This
       
   410 constructor does not allocate any private data for `ObjectOutputStream` and
       
   411 sets a flag that indicates that the final `writeObject` method should invoke
       
   412 the `writeObjectOverride` method and return. All other `ObjectOutputStream`
       
   413 methods are not final and can be directly overridden by the subclass.
       
   414 
       
   415 ## 2.2 The ObjectOutputStream.PutField Class
       
   416 
       
   417 Class `PutField` provides the API for setting values of the serializable fields
       
   418 for a class when the class does not use default serialization. Each method puts
       
   419 the specified named value into the stream. An `IllegalArgumentException` is
       
   420 thrown if `name` does not match the name of a serializable field for the class
       
   421 whose fields are being written, or if the type of the named field does not
       
   422 match the second parameter type of the specific `put` method invoked.
       
   423 
       
   424 ## 2.3 The writeObject Method
       
   425 
       
   426 For serializable objects, the `writeObject` method allows a class to control
       
   427 the serialization of its own fields. Here is its signature:
       
   428 
       
   429 ```
       
   430 private void writeObject(ObjectOutputStream stream)
       
   431     throws IOException;
       
   432 ```
       
   433 
       
   434 Each subclass of a serializable object may define its own `writeObject` method.
       
   435 If a class does not implement the method, the default serialization provided by
       
   436 `defaultWriteObject` will be used. When implemented, the class is only
       
   437 responsible for writing its own fields, not those of its supertypes or
       
   438 subtypes.
       
   439 
       
   440 The class's `writeObject` method, if implemented, is responsible for saving the
       
   441 state of the class. Either `ObjectOutputStream`'s `defaultWriteObject` or
       
   442 `writeFields` method must be called once (and only once) before writing any
       
   443 optional data that will be needed by the corresponding `readObject` method to
       
   444 restore the state of the object; even if no optional data is written,
       
   445 `defaultWriteObject` or `writeFields` must still be invoked once. If
       
   446 `defaultWriteObject` or `writeFields` is not invoked once prior to the writing
       
   447 of optional data (if any), then the behavior of instance deserialization is
       
   448 undefined in cases where the `ObjectInputStream` cannot resolve the class which
       
   449 defined the `writeObject` method in question.
       
   450 
       
   451 The responsibility for the format, structure, and versioning of the optional
       
   452 data lies completely with the class.
       
   453 
       
   454 ## 2.4 The writeExternal Method
       
   455 
       
   456 Objects implementing `java.io.Externalizable` must implement the
       
   457 `writeExternal` method to save the entire state of the object. It must
       
   458 coordinate with its superclasses to save their state. All of the methods of
       
   459 `ObjectOutput` are available to save the object's primitive typed fields and
       
   460 object fields.
       
   461 
       
   462 ```
       
   463 public void writeExternal(ObjectOutput stream)
       
   464     throws IOException;
       
   465 ```
       
   466 
       
   467 A new default format for writing Externalizable data has been introduced in JDK
       
   468 1.2. The new format specifies that primitive data will be written in block data
       
   469 mode by `writeExternal` methods. Additionally, a tag denoting the end of the
       
   470 External object is appended to the stream after the `writeExternal` method
       
   471 returns. The benefits of this format change are discussed in [Section 3.6, "The
       
   472 readExternal Method"](input.html#the-readexternal-method). Compatibility issues
       
   473 caused by this change are discussed in [Section 2.6, "The useProtocolVersion
       
   474 Method"](#the-useprotocolversion-method).
       
   475 
       
   476 ## 2.5 The writeReplace Method
       
   477 
       
   478 For Serializable and Externalizable classes, the `writeReplace` method allows a
       
   479 class of an object to nominate its own replacement in the stream before the
       
   480 object is written. By implementing the `writeReplace` method, a class can
       
   481 directly control the types and instances of its own instances being serialized.
       
   482 
       
   483 The method is defined as follows:
       
   484 
       
   485 ```
       
   486 ANY-ACCESS-MODIFIER Object writeReplace()
       
   487              throws ObjectStreamException;
       
   488 ```
       
   489 
       
   490 The `writeReplace` method is called when `ObjectOutputStream` is preparing to
       
   491 write the object to the stream. The `ObjectOutputStream` checks whether the
       
   492 class defines the `writeReplace` method. If the method is defined, the
       
   493 `writeReplace` method is called to allow the object to designate its
       
   494 replacement in the stream. The object returned should be either of the same
       
   495 type as the object passed in or an object that when read and resolved will
       
   496 result in an object of a type that is compatible with all references to the
       
   497 object. If it is not, a `ClassCastException` will occur when the type mismatch
       
   498 is discovered.
       
   499 
       
   500 ## 2.6 The useProtocolVersion Method
       
   501 
       
   502 Due to a stream protocol change that was not backwards compatible, a mechanism
       
   503 has been added to enable the current Virtual Machine to write a serialization
       
   504 stream that is readable by a previous release. Of course, the problems that are
       
   505 corrected by the new stream format will exist when using the backwards
       
   506 compatible protocol.
       
   507 
       
   508 Stream protocol versions are discussed in [Section 6.3, "Stream Protocol
       
   509 Versions"](protocol.html#stream-protocol-versions).
       
   510 
       
   511 -------------------------------------------------------------------------------
       
   512 
       
   513 *[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
       
   514 and/or its affiliates. All rights reserved.*