src/java.base/share/classes/java/io/ObjectInputStream.java

Print this page




  23  * questions.
  24  */
  25 
  26 package java.io;
  27 
  28 import java.io.ObjectStreamClass.WeakClassKey;
  29 import java.lang.ref.ReferenceQueue;
  30 import java.lang.reflect.Array;
  31 import java.lang.reflect.Modifier;
  32 import java.lang.reflect.Proxy;
  33 import java.security.AccessControlContext;
  34 import java.security.AccessController;
  35 import java.security.PrivilegedAction;
  36 import java.security.PrivilegedActionException;
  37 import java.security.PrivilegedExceptionAction;
  38 import java.util.Arrays;
  39 import java.util.HashMap;
  40 import java.util.concurrent.ConcurrentHashMap;
  41 import java.util.concurrent.ConcurrentMap;
  42 import static java.io.ObjectStreamClass.processQueue;

  43 import sun.reflect.misc.ReflectUtil;
  44 
  45 /**
  46  * An ObjectInputStream deserializes primitive data and objects previously
  47  * written using an ObjectOutputStream.
  48  *
  49  * <p>ObjectOutputStream and ObjectInputStream can provide an application with
  50  * persistent storage for graphs of objects when used with a FileOutputStream
  51  * and FileInputStream respectively.  ObjectInputStream is used to recover
  52  * those objects previously serialized. Other uses include passing objects
  53  * between hosts using a socket stream or for marshaling and unmarshaling
  54  * arguments and parameters in a remote communication system.
  55  *
  56  * <p>ObjectInputStream ensures that the types of all objects in the graph
  57  * created from the stream match the classes present in the Java Virtual
  58  * Machine.  Classes are loaded as required using the standard mechanisms.
  59  *
  60  * <p>Only objects that support the java.io.Serializable or
  61  * java.io.Externalizable interface can be read from streams.
  62  *


 251     private int passHandle = NULL_HANDLE;
 252     /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
 253     private boolean defaultDataEnd = false;
 254 
 255     /** buffer for reading primitive field values */
 256     private byte[] primVals;
 257 
 258     /** if true, invoke readObjectOverride() instead of readObject() */
 259     private final boolean enableOverride;
 260     /** if true, invoke resolveObject() */
 261     private boolean enableResolve;
 262 
 263     /**
 264      * Context during upcalls to class-defined readObject methods; holds
 265      * object currently being deserialized and descriptor for current class.
 266      * Null when not during readObject upcall.
 267      */
 268     private SerialCallbackContext curContext;
 269 
 270     /**










 271      * Creates an ObjectInputStream that reads from the specified InputStream.
 272      * A serialization stream header is read from the stream and verified.
 273      * This constructor will block until the corresponding ObjectOutputStream
 274      * has written and flushed the header.
 275      *
 276      * <p>If a security manager is installed, this constructor will check for
 277      * the "enableSubclassImplementation" SerializablePermission when invoked
 278      * directly or indirectly by the constructor of a subclass which overrides
 279      * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
 280      * methods.
 281      *
 282      * @param   in input stream to read from
 283      * @throws  StreamCorruptedException if the stream header is incorrect
 284      * @throws  IOException if an I/O error occurs while reading stream header
 285      * @throws  SecurityException if untrusted subclass illegally overrides
 286      *          security-sensitive methods
 287      * @throws  NullPointerException if <code>in</code> is <code>null</code>
 288      * @see     ObjectInputStream#ObjectInputStream()
 289      * @see     ObjectInputStream#readFields()
 290      * @see     ObjectOutputStream#ObjectOutputStream(OutputStream)


 358      * @throws  IOException Any of the usual Input/Output related exceptions.
 359      */
 360     public final Object readObject()
 361         throws IOException, ClassNotFoundException
 362     {
 363         if (enableOverride) {
 364             return readObjectOverride();
 365         }
 366 
 367         // if nested read, passHandle contains handle of enclosing object
 368         int outerHandle = passHandle;
 369         try {
 370             Object obj = readObject0(false);
 371             handles.markDependency(outerHandle, passHandle);
 372             ClassNotFoundException ex = handles.lookupException(passHandle);
 373             if (ex != null) {
 374                 throw ex;
 375             }
 376             if (depth == 0) {
 377                 vlist.doCallbacks();



 378             }
 379             return obj;
 380         } finally {
 381             passHandle = outerHandle;
 382             if (closed && depth == 0) {
 383                 clear();
 384             }
 385         }
 386     }
 387 
 388     /**
 389      * This method is called by trusted subclasses of ObjectOutputStream that
 390      * constructed ObjectOutputStream using the protected no-arg constructor.
 391      * The subclass is expected to provide an override method with the modifier
 392      * "final".
 393      *
 394      * @return  the Object read from the stream.
 395      * @throws  ClassNotFoundException Class definition of a serialized object
 396      *          cannot be found.
 397      * @throws  OptionalDataException Primitive data was found in the stream


 448      * @throws  StreamCorruptedException if control information in the stream
 449      *          is inconsistent
 450      * @throws  ObjectStreamException if object to deserialize has already
 451      *          appeared in stream
 452      * @throws  OptionalDataException if primitive data is next in stream
 453      * @throws  IOException if an I/O error occurs during deserialization
 454      * @since   1.4
 455      */
 456     public Object readUnshared() throws IOException, ClassNotFoundException {
 457         // if nested read, passHandle contains handle of enclosing object
 458         int outerHandle = passHandle;
 459         try {
 460             Object obj = readObject0(true);
 461             handles.markDependency(outerHandle, passHandle);
 462             ClassNotFoundException ex = handles.lookupException(passHandle);
 463             if (ex != null) {
 464                 throw ex;
 465             }
 466             if (depth == 0) {
 467                 vlist.doCallbacks();



 468             }
 469             return obj;
 470         } finally {
 471             passHandle = outerHandle;
 472             if (closed && depth == 0) {
 473                 clear();
 474             }
 475         }
 476     }
 477 
 478     /**
 479      * Read the non-static and non-transient fields of the current class from
 480      * this stream.  This may only be called from the readObject method of the
 481      * class being deserialized. It will throw the NotActiveException if it is
 482      * called otherwise.
 483      *
 484      * @throws  ClassNotFoundException if the class of a serialized object
 485      *          could not be found.
 486      * @throws  IOException if an I/O error occurs.
 487      * @throws  NotActiveException if the stream is not currently reading


1861          * CNFException, then the stream is probably in an inconsistent state,
1862          * since some (or all) of the externalizable data may not have been
1863          * consumed.  Since there's no "correct" action to take in this case,
1864          * we mimic the behavior of past serialization implementations and
1865          * blindly hope that the stream is in sync; if it isn't and additional
1866          * externalizable data remains in the stream, a subsequent read will
1867          * most likely throw a StreamCorruptedException.
1868          */
1869     }
1870 
1871     /**
1872      * Reads (or attempts to skip, if obj is null or is tagged with a
1873      * ClassNotFoundException) instance data for each serializable class of
1874      * object in stream, from superclass to subclass.  Expects that passHandle
1875      * is set to obj's handle before this method is called.
1876      */
1877     private void readSerialData(Object obj, ObjectStreamClass desc)
1878         throws IOException
1879     {
1880         ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();

1881         for (int i = 0; i < slots.length; i++) {
1882             ObjectStreamClass slotDesc = slots[i].desc;



1883 
1884             if (slots[i].hasData) {
1885                 if (obj != null &&
1886                     slotDesc.hasReadObjectMethod() &&
1887                     handles.lookupException(passHandle) == null)
1888                 {
1889                     SerialCallbackContext oldContext = curContext;
1890 
1891                     try {
1892                         curContext = new SerialCallbackContext(obj, slotDesc);
1893 
1894                         bin.setBlockDataMode(true);
1895                         slotDesc.invokeReadObject(obj, this);
1896                     } catch (ClassNotFoundException ex) {
1897                         /*
1898                          * In most cases, the handle table has already
1899                          * propagated a CNFException to passHandle at this
1900                          * point; this mark call is included to address cases
1901                          * where the custom readObject method has cons'ed and
1902                          * thrown a new CNFException of its own.


1913                      * readFields(); clear it to restore normal read behavior.
1914                      */
1915                     defaultDataEnd = false;
1916                 } else {
1917                     defaultReadFields(obj, slotDesc);
1918                 }
1919                 if (slotDesc.hasWriteObjectData()) {
1920                     skipCustomData();
1921                 } else {
1922                     bin.setBlockDataMode(false);
1923                 }
1924             } else {
1925                 if (obj != null &&
1926                     slotDesc.hasReadObjectNoDataMethod() &&
1927                     handles.lookupException(passHandle) == null)
1928                 {
1929                     slotDesc.invokeReadObjectNoData(obj);
1930                 }
1931             }
1932         }

1933     }
1934 
1935     /**
1936      * Skips over all block data and objects until TC_ENDBLOCKDATA is
1937      * encountered.
1938      */
1939     private void skipCustomData() throws IOException {
1940         int oldHandle = passHandle;
1941         for (;;) {
1942             if (bin.getBlockDataMode()) {
1943                 bin.skipBlockData();
1944                 bin.setBlockDataMode(false);
1945             }
1946             switch (bin.peekByte()) {
1947                 case TC_BLOCKDATA:
1948                 case TC_BLOCKDATALONG:
1949                     bin.setBlockDataMode(true);
1950                     break;
1951 
1952                 case TC_ENDBLOCKDATA:


2340                 return 0;
2341             }
2342             int skipped = 0;
2343             if (peekb >= 0) {
2344                 peekb = -1;
2345                 skipped++;
2346                 n--;
2347             }
2348             return skipped + in.skip(n);
2349         }
2350 
2351         public int available() throws IOException {
2352             return in.available() + ((peekb >= 0) ? 1 : 0);
2353         }
2354 
2355         public void close() throws IOException {
2356             in.close();
2357         }
2358     }
2359 









2360     /**
2361      * Input stream with two modes: in default mode, inputs data written in the
2362      * same format as DataOutputStream; in "block data" mode, inputs data
2363      * bracketed by block data markers (see object serialization specification
2364      * for details).  Buffering depends on block data mode: when in default
2365      * mode, no data is buffered in advance; when in block data mode, all data
2366      * for the current data block is read in at once (and buffered).
2367      */
2368     private class BlockDataInputStream
2369         extends InputStream implements DataInput
2370     {
2371         /** maximum data block length */
2372         private static final int MAX_BLOCK_SIZE = 1024;
2373         /** maximum data block header length */
2374         private static final int MAX_HEADER_SIZE = 5;
2375         /** (tunable) length of char buffer (for reading strings) */
2376         private static final int CHAR_BUF_SIZE = 256;
2377         /** readBlockHeader() return value indicating header read may block */
2378         private static final int HEADER_BLOCKED = -2;
2379 




  23  * questions.
  24  */
  25 
  26 package java.io;
  27 
  28 import java.io.ObjectStreamClass.WeakClassKey;
  29 import java.lang.ref.ReferenceQueue;
  30 import java.lang.reflect.Array;
  31 import java.lang.reflect.Modifier;
  32 import java.lang.reflect.Proxy;
  33 import java.security.AccessControlContext;
  34 import java.security.AccessController;
  35 import java.security.PrivilegedAction;
  36 import java.security.PrivilegedActionException;
  37 import java.security.PrivilegedExceptionAction;
  38 import java.util.Arrays;
  39 import java.util.HashMap;
  40 import java.util.concurrent.ConcurrentHashMap;
  41 import java.util.concurrent.ConcurrentMap;
  42 import static java.io.ObjectStreamClass.processQueue;
  43 import sun.misc.Unsafe;
  44 import sun.reflect.misc.ReflectUtil;
  45 
  46 /**
  47  * An ObjectInputStream deserializes primitive data and objects previously
  48  * written using an ObjectOutputStream.
  49  *
  50  * <p>ObjectOutputStream and ObjectInputStream can provide an application with
  51  * persistent storage for graphs of objects when used with a FileOutputStream
  52  * and FileInputStream respectively.  ObjectInputStream is used to recover
  53  * those objects previously serialized. Other uses include passing objects
  54  * between hosts using a socket stream or for marshaling and unmarshaling
  55  * arguments and parameters in a remote communication system.
  56  *
  57  * <p>ObjectInputStream ensures that the types of all objects in the graph
  58  * created from the stream match the classes present in the Java Virtual
  59  * Machine.  Classes are loaded as required using the standard mechanisms.
  60  *
  61  * <p>Only objects that support the java.io.Serializable or
  62  * java.io.Externalizable interface can be read from streams.
  63  *


 252     private int passHandle = NULL_HANDLE;
 253     /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
 254     private boolean defaultDataEnd = false;
 255 
 256     /** buffer for reading primitive field values */
 257     private byte[] primVals;
 258 
 259     /** if true, invoke readObjectOverride() instead of readObject() */
 260     private final boolean enableOverride;
 261     /** if true, invoke resolveObject() */
 262     private boolean enableResolve;
 263 
 264     /**
 265      * Context during upcalls to class-defined readObject methods; holds
 266      * object currently being deserialized and descriptor for current class.
 267      * Null when not during readObject upcall.
 268      */
 269     private SerialCallbackContext curContext;
 270 
 271     /**
 272      * Tracks whether deserialization of an object in the graph may have set
 273      * a final field, and therefore requires a freeze action before returning
 274      * the graph of objects from the topmost readObject call.
 275      * Nested calls to readObject do not issue freeze actions because the
 276      * sub-graph returned from a nested call is not guaranteed to be fully
 277      * initialized yet (possible cycles).
 278      */
 279     private boolean requiresFreeze;
 280 
 281     /**
 282      * Creates an ObjectInputStream that reads from the specified InputStream.
 283      * A serialization stream header is read from the stream and verified.
 284      * This constructor will block until the corresponding ObjectOutputStream
 285      * has written and flushed the header.
 286      *
 287      * <p>If a security manager is installed, this constructor will check for
 288      * the "enableSubclassImplementation" SerializablePermission when invoked
 289      * directly or indirectly by the constructor of a subclass which overrides
 290      * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
 291      * methods.
 292      *
 293      * @param   in input stream to read from
 294      * @throws  StreamCorruptedException if the stream header is incorrect
 295      * @throws  IOException if an I/O error occurs while reading stream header
 296      * @throws  SecurityException if untrusted subclass illegally overrides
 297      *          security-sensitive methods
 298      * @throws  NullPointerException if <code>in</code> is <code>null</code>
 299      * @see     ObjectInputStream#ObjectInputStream()
 300      * @see     ObjectInputStream#readFields()
 301      * @see     ObjectOutputStream#ObjectOutputStream(OutputStream)


 369      * @throws  IOException Any of the usual Input/Output related exceptions.
 370      */
 371     public final Object readObject()
 372         throws IOException, ClassNotFoundException
 373     {
 374         if (enableOverride) {
 375             return readObjectOverride();
 376         }
 377 
 378         // if nested read, passHandle contains handle of enclosing object
 379         int outerHandle = passHandle;
 380         try {
 381             Object obj = readObject0(false);
 382             handles.markDependency(outerHandle, passHandle);
 383             ClassNotFoundException ex = handles.lookupException(passHandle);
 384             if (ex != null) {
 385                 throw ex;
 386             }
 387             if (depth == 0) {
 388                 vlist.doCallbacks();
 389                 if (requiresFreeze) {
 390                     freeze();
 391                 }
 392             }
 393             return obj;
 394         } finally {
 395             passHandle = outerHandle;
 396             if (closed && depth == 0) {
 397                 clear();
 398             }
 399         }
 400     }
 401 
 402     /**
 403      * This method is called by trusted subclasses of ObjectOutputStream that
 404      * constructed ObjectOutputStream using the protected no-arg constructor.
 405      * The subclass is expected to provide an override method with the modifier
 406      * "final".
 407      *
 408      * @return  the Object read from the stream.
 409      * @throws  ClassNotFoundException Class definition of a serialized object
 410      *          cannot be found.
 411      * @throws  OptionalDataException Primitive data was found in the stream


 462      * @throws  StreamCorruptedException if control information in the stream
 463      *          is inconsistent
 464      * @throws  ObjectStreamException if object to deserialize has already
 465      *          appeared in stream
 466      * @throws  OptionalDataException if primitive data is next in stream
 467      * @throws  IOException if an I/O error occurs during deserialization
 468      * @since   1.4
 469      */
 470     public Object readUnshared() throws IOException, ClassNotFoundException {
 471         // if nested read, passHandle contains handle of enclosing object
 472         int outerHandle = passHandle;
 473         try {
 474             Object obj = readObject0(true);
 475             handles.markDependency(outerHandle, passHandle);
 476             ClassNotFoundException ex = handles.lookupException(passHandle);
 477             if (ex != null) {
 478                 throw ex;
 479             }
 480             if (depth == 0) {
 481                 vlist.doCallbacks();
 482                 if (requiresFreeze) {
 483                     freeze();
 484                 }
 485             }
 486             return obj;
 487         } finally {
 488             passHandle = outerHandle;
 489             if (closed && depth == 0) {
 490                 clear();
 491             }
 492         }
 493     }
 494 
 495     /**
 496      * Read the non-static and non-transient fields of the current class from
 497      * this stream.  This may only be called from the readObject method of the
 498      * class being deserialized. It will throw the NotActiveException if it is
 499      * called otherwise.
 500      *
 501      * @throws  ClassNotFoundException if the class of a serialized object
 502      *          could not be found.
 503      * @throws  IOException if an I/O error occurs.
 504      * @throws  NotActiveException if the stream is not currently reading


1878          * CNFException, then the stream is probably in an inconsistent state,
1879          * since some (or all) of the externalizable data may not have been
1880          * consumed.  Since there's no "correct" action to take in this case,
1881          * we mimic the behavior of past serialization implementations and
1882          * blindly hope that the stream is in sync; if it isn't and additional
1883          * externalizable data remains in the stream, a subsequent read will
1884          * most likely throw a StreamCorruptedException.
1885          */
1886     }
1887 
1888     /**
1889      * Reads (or attempts to skip, if obj is null or is tagged with a
1890      * ClassNotFoundException) instance data for each serializable class of
1891      * object in stream, from superclass to subclass.  Expects that passHandle
1892      * is set to obj's handle before this method is called.
1893      */
1894     private void readSerialData(Object obj, ObjectStreamClass desc)
1895         throws IOException
1896     {
1897         ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
1898         boolean freeze = false;
1899         for (int i = 0; i < slots.length; i++) {
1900             ObjectStreamClass slotDesc = slots[i].desc;
1901             if (!freeze && slotDesc.hasFinalField()) {
1902                 freeze = true;
1903             }
1904 
1905             if (slots[i].hasData) {
1906                 if (obj != null &&
1907                     slotDesc.hasReadObjectMethod() &&
1908                     handles.lookupException(passHandle) == null)
1909                 {
1910                     SerialCallbackContext oldContext = curContext;
1911 
1912                     try {
1913                         curContext = new SerialCallbackContext(obj, slotDesc);
1914 
1915                         bin.setBlockDataMode(true);
1916                         slotDesc.invokeReadObject(obj, this);
1917                     } catch (ClassNotFoundException ex) {
1918                         /*
1919                          * In most cases, the handle table has already
1920                          * propagated a CNFException to passHandle at this
1921                          * point; this mark call is included to address cases
1922                          * where the custom readObject method has cons'ed and
1923                          * thrown a new CNFException of its own.


1934                      * readFields(); clear it to restore normal read behavior.
1935                      */
1936                     defaultDataEnd = false;
1937                 } else {
1938                     defaultReadFields(obj, slotDesc);
1939                 }
1940                 if (slotDesc.hasWriteObjectData()) {
1941                     skipCustomData();
1942                 } else {
1943                     bin.setBlockDataMode(false);
1944                 }
1945             } else {
1946                 if (obj != null &&
1947                     slotDesc.hasReadObjectNoDataMethod() &&
1948                     handles.lookupException(passHandle) == null)
1949                 {
1950                     slotDesc.invokeReadObjectNoData(obj);
1951                 }
1952             }
1953         }
1954         requiresFreeze = freeze;
1955     }
1956 
1957     /**
1958      * Skips over all block data and objects until TC_ENDBLOCKDATA is
1959      * encountered.
1960      */
1961     private void skipCustomData() throws IOException {
1962         int oldHandle = passHandle;
1963         for (;;) {
1964             if (bin.getBlockDataMode()) {
1965                 bin.skipBlockData();
1966                 bin.setBlockDataMode(false);
1967             }
1968             switch (bin.peekByte()) {
1969                 case TC_BLOCKDATA:
1970                 case TC_BLOCKDATALONG:
1971                     bin.setBlockDataMode(true);
1972                     break;
1973 
1974                 case TC_ENDBLOCKDATA:


2362                 return 0;
2363             }
2364             int skipped = 0;
2365             if (peekb >= 0) {
2366                 peekb = -1;
2367                 skipped++;
2368                 n--;
2369             }
2370             return skipped + in.skip(n);
2371         }
2372 
2373         public int available() throws IOException {
2374             return in.available() + ((peekb >= 0) ? 1 : 0);
2375         }
2376 
2377         public void close() throws IOException {
2378             in.close();
2379         }
2380     }
2381 
2382     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
2383 
2384     private void freeze() {
2385         // Issue a storestore|storeload fence, which is at least sufficient
2386         // to provide final-freeze semantics. 
2387         UNSAFE.storeFence();
2388         requiresFreeze = false;
2389     }
2390 
2391     /**
2392      * Input stream with two modes: in default mode, inputs data written in the
2393      * same format as DataOutputStream; in "block data" mode, inputs data
2394      * bracketed by block data markers (see object serialization specification
2395      * for details).  Buffering depends on block data mode: when in default
2396      * mode, no data is buffered in advance; when in block data mode, all data
2397      * for the current data block is read in at once (and buffered).
2398      */
2399     private class BlockDataInputStream
2400         extends InputStream implements DataInput
2401     {
2402         /** maximum data block length */
2403         private static final int MAX_BLOCK_SIZE = 1024;
2404         /** maximum data block header length */
2405         private static final int MAX_HEADER_SIZE = 5;
2406         /** (tunable) length of char buffer (for reading strings) */
2407         private static final int CHAR_BUF_SIZE = 256;
2408         /** readBlockHeader() return value indicating header read may block */
2409         private static final int HEADER_BLOCKED = -2;
2410