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

Print this page




 236         static final ReferenceQueue<Class<?>> subclassAuditsQueue =
 237             new ReferenceQueue<>();
 238     }
 239 
 240     /** filter stream for handling block data conversion */
 241     private final BlockDataInputStream bin;
 242     /** validation callback list */
 243     private final ValidationList vlist;
 244     /** recursion depth */
 245     private int depth;
 246     /** whether stream is closed */
 247     private boolean closed;
 248 
 249     /** wire handle -> obj/exception map */
 250     private final HandleTable handles;
 251     /** scratch field for passing handle values up/down call stack */
 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      * Creates an ObjectInputStream that reads from the specified InputStream.
 273      * A serialization stream header is read from the stream and verified.
 274      * This constructor will block until the corresponding ObjectOutputStream
 275      * has written and flushed the header.
 276      *
 277      * <p>If a security manager is installed, this constructor will check for
 278      * the "enableSubclassImplementation" SerializablePermission when invoked


 483      * this stream.  This may only be called from the readObject method of the
 484      * class being deserialized. It will throw the NotActiveException if it is
 485      * called otherwise.
 486      *
 487      * @throws  ClassNotFoundException if the class of a serialized object
 488      *          could not be found.
 489      * @throws  IOException if an I/O error occurs.
 490      * @throws  NotActiveException if the stream is not currently reading
 491      *          objects.
 492      */
 493     public void defaultReadObject()
 494         throws IOException, ClassNotFoundException
 495     {
 496         SerialCallbackContext ctx = curContext;
 497         if (ctx == null) {
 498             throw new NotActiveException("not in call to readObject");
 499         }
 500         Object curObj = ctx.getObj();
 501         ObjectStreamClass curDesc = ctx.getDesc();
 502         bin.setBlockDataMode(false);
 503         defaultReadFields(curObj, curDesc);




 504         bin.setBlockDataMode(true);
 505         if (!curDesc.hasWriteObjectData()) {
 506             /*
 507              * Fix for 4360508: since stream does not contain terminating
 508              * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
 509              * knows to simulate end-of-custom-data behavior.
 510              */
 511             defaultDataEnd = true;
 512         }
 513         ClassNotFoundException ex = handles.lookupException(passHandle);
 514         if (ex != null) {
 515             throw ex;
 516         }
 517     }
 518 
 519     /**
 520      * Reads the persistent fields from the stream and makes them available by
 521      * name.
 522      *
 523      * @return  the <code>GetField</code> object representing the persistent


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




















1884         for (int i = 0; i < slots.length; i++) {
1885             ObjectStreamClass slotDesc = slots[i].desc;
1886 
1887             if (slots[i].hasData) {
1888                 if (obj != null &&
1889                     slotDesc.hasReadObjectMethod() &&
1890                     handles.lookupException(passHandle) == null)
1891                 {
1892                     SerialCallbackContext oldContext = curContext;
1893 
1894                     try {
1895                         curContext = new SerialCallbackContext(obj, slotDesc);
1896 
1897                         bin.setBlockDataMode(true);
1898                         slotDesc.invokeReadObject(obj, this);
1899                     } catch (ClassNotFoundException ex) {
1900                         /*
1901                          * In most cases, the handle table has already
1902                          * propagated a CNFException to passHandle at this
1903                          * point; this mark call is included to address cases
1904                          * where the custom readObject method has cons'ed and
1905                          * thrown a new CNFException of its own.
1906                          */
1907                         handles.markException(passHandle, ex);
1908                     } finally {
1909                         curContext.setUsed();
1910                         curContext = oldContext;
1911                     }
1912 
1913                     /*
1914                      * defaultDataEnd may have been set indirectly by custom
1915                      * readObject() method when calling defaultReadObject() or
1916                      * readFields(); clear it to restore normal read behavior.
1917                      */
1918                     defaultDataEnd = false;
1919                 } else {
1920                     defaultReadFields(obj, slotDesc);






1921                 }
1922                 if (slotDesc.hasWriteObjectData()) {
1923                     skipCustomData();
1924                 } else {
1925                     bin.setBlockDataMode(false);
1926                 }
1927             } else {
1928                 if (obj != null &&
1929                     slotDesc.hasReadObjectNoDataMethod() &&
1930                     handles.lookupException(passHandle) == null)
1931                 {
1932                     slotDesc.invokeReadObjectNoData(obj);
1933                 }
1934             }
1935         }













1936     }
1937 
1938     /**
1939      * Skips over all block data and objects until TC_ENDBLOCKDATA is
1940      * encountered.
1941      */
1942     private void skipCustomData() throws IOException {
1943         int oldHandle = passHandle;
1944         for (;;) {
1945             if (bin.getBlockDataMode()) {
1946                 bin.skipBlockData();
1947                 bin.setBlockDataMode(false);
1948             }
1949             switch (bin.peekByte()) {
1950                 case TC_BLOCKDATA:
1951                 case TC_BLOCKDATALONG:
1952                     bin.setBlockDataMode(true);
1953                     break;
1954 
1955                 case TC_ENDBLOCKDATA:
1956                     bin.readByte();
1957                     passHandle = oldHandle;
1958                     return;
1959 
1960                 default:
1961                     readObject0(false);
1962                     break;
1963             }
1964         }
1965     }
1966 










1967     /**
1968      * Reads in values of serializable fields declared by given class
1969      * descriptor.  If obj is non-null, sets field values in obj.  Expects that
1970      * passHandle is set to obj's handle before this method is called.
1971      */
1972     private void defaultReadFields(Object obj, ObjectStreamClass desc)
1973         throws IOException
1974     {
1975         Class<?> cl = desc.forClass();
1976         if (cl != null && obj != null && !cl.isInstance(obj)) {
1977             throw new ClassCastException();
1978         }
1979 

1980         int primDataSize = desc.getPrimDataSize();
1981         if (primDataSize > 0) {
1982             if (primVals == null || primVals.length < primDataSize) {
1983                 primVals = new byte[primDataSize];
1984             }
1985             bin.readFully(primVals, 0, primDataSize, false);
1986             if (obj != null) {
1987                 desc.setPrimFieldValues(obj, primVals);
1988             }
1989         }
1990 

1991         int numObjFields = desc.getNumObjFields();
1992         if (numObjFields > 0) {
1993             int objHandle = passHandle;
1994             ObjectStreamField[] fields = desc.getFields(false);
1995             Object[] objVals = new Object[numObjFields];
1996             int numPrimFields = fields.length - objVals.length;
1997             for (int i = 0; i < objVals.length; i++) {
1998                 ObjectStreamField f = fields[numPrimFields + i];
1999                 objVals[i] = readObject0(f.isUnshared());
2000                 if (f.getField() != null) {
2001                     handles.markDependency(objHandle, passHandle);
2002                 }
2003             }
2004             if (obj != null) {
2005                 desc.setObjFieldValues(obj, objVals);
2006             }
2007             passHandle = objHandle;
2008         }






















2009     }
2010 
2011     /**
2012      * Reads in and returns IOException that caused serialization to abort.
2013      * All stream state is discarded prior to reading in fatal exception.  Sets
2014      * passHandle to fatal exception's handle.
2015      */
2016     private IOException readFatalException() throws IOException {
2017         if (bin.readByte() != TC_EXCEPTION) {
2018             throw new InternalError();
2019         }
2020         clear();
2021         return (IOException) readObject0(false);
2022     }
2023 
2024     /**
2025      * If recursion depth is 0, clears internal data structures; otherwise,
2026      * throws a StreamCorruptedException.  This method is called when a
2027      * TC_RESET typecode is encountered.
2028      */




 236         static final ReferenceQueue<Class<?>> subclassAuditsQueue =
 237             new ReferenceQueue<>();
 238     }
 239 
 240     /** filter stream for handling block data conversion */
 241     private final BlockDataInputStream bin;
 242     /** validation callback list */
 243     private final ValidationList vlist;
 244     /** recursion depth */
 245     private int depth;
 246     /** whether stream is closed */
 247     private boolean closed;
 248 
 249     /** wire handle -> obj/exception map */
 250     private final HandleTable handles;
 251     /** scratch field for passing handle values up/down call stack */
 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     /** if true, invoke readObjectOverride() instead of readObject() */
 257     private final boolean enableOverride;
 258     /** if true, invoke resolveObject() */
 259     private boolean enableResolve;
 260 
 261     /**
 262      * Context during upcalls to class-defined readObject methods; holds
 263      * object currently being deserialized and descriptor for current class.
 264      * Null when not during readObject upcall.
 265      */
 266     private SerialCallbackContext curContext;
 267 
 268     /**
 269      * Creates an ObjectInputStream that reads from the specified InputStream.
 270      * A serialization stream header is read from the stream and verified.
 271      * This constructor will block until the corresponding ObjectOutputStream
 272      * has written and flushed the header.
 273      *
 274      * <p>If a security manager is installed, this constructor will check for
 275      * the "enableSubclassImplementation" SerializablePermission when invoked


 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
 488      *          objects.
 489      */
 490     public void defaultReadObject()
 491         throws IOException, ClassNotFoundException
 492     {
 493         SerialCallbackContext ctx = curContext;
 494         if (ctx == null) {
 495             throw new NotActiveException("not in call to readObject");
 496         }
 497         Object curObj = ctx.getObj();
 498         ObjectStreamClass curDesc = ctx.getDesc();
 499         bin.setBlockDataMode(false);
 500         FieldValues vals = defaultReadFields(curObj, curDesc);
 501         if (curObj != null) {
 502             defaultCheckFieldValues(curObj, curDesc, vals);
 503             defaultSetFieldValues(curObj, curDesc, vals);
 504         }
 505         bin.setBlockDataMode(true);
 506         if (!curDesc.hasWriteObjectData()) {
 507             /*
 508              * Fix for 4360508: since stream does not contain terminating
 509              * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
 510              * knows to simulate end-of-custom-data behavior.
 511              */
 512             defaultDataEnd = true;
 513         }
 514         ClassNotFoundException ex = handles.lookupException(passHandle);
 515         if (ex != null) {
 516             throw ex;
 517         }
 518     }
 519 
 520     /**
 521      * Reads the persistent fields from the stream and makes them available by
 522      * name.
 523      *
 524      * @return  the <code>GetField</code> object representing the persistent


1865          * CNFException, then the stream is probably in an inconsistent state,
1866          * since some (or all) of the externalizable data may not have been
1867          * consumed.  Since there's no "correct" action to take in this case,
1868          * we mimic the behavior of past serialization implementations and
1869          * blindly hope that the stream is in sync; if it isn't and additional
1870          * externalizable data remains in the stream, a subsequent read will
1871          * most likely throw a StreamCorruptedException.
1872          */
1873     }
1874 
1875     /**
1876      * Reads (or attempts to skip, if obj is null or is tagged with a
1877      * ClassNotFoundException) instance data for each serializable class of
1878      * object in stream, from superclass to subclass.  Expects that passHandle
1879      * is set to obj's handle before this method is called.
1880      */
1881     private void readSerialData(Object obj, ObjectStreamClass desc)
1882         throws IOException
1883     {
1884         ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
1885         // Best effort Failure Atomicity; slotValues will be non-null if field
1886         // values can be set after reading all field data in the hierarchy.
1887         // Field values can only be set after reading all data if there are no
1888         // user observable methods in the hierarchy, readObject(NoData). The
1889         // top most Serializable class in the hierarchy can be skipped.
1890         FieldValues[] slotValues = null;
1891 
1892         boolean hasSpecialReadMethod = false;
1893         for (int i = 1; i < slots.length; i++) {
1894             ObjectStreamClass slotDesc = slots[i].desc;
1895             if (slotDesc.hasReadObjectMethod()
1896                   || slotDesc.hasReadObjectNoDataMethod()) {
1897                 hasSpecialReadMethod = true;
1898                 break;
1899             }
1900         }
1901         // No special read methods, can store values and defer setting.
1902         if (!hasSpecialReadMethod)
1903             slotValues = new FieldValues[slots.length];
1904 
1905         for (int i = 0; i < slots.length; i++) {
1906             ObjectStreamClass slotDesc = slots[i].desc;
1907 
1908             if (slots[i].hasData) {
1909                 if (obj != null &&
1910                     slotDesc.hasReadObjectMethod() &&
1911                     handles.lookupException(passHandle) == null)
1912                 {
1913                     SerialCallbackContext oldContext = curContext;
1914 
1915                     try {
1916                         curContext = new SerialCallbackContext(obj, slotDesc);
1917 
1918                         bin.setBlockDataMode(true);
1919                         slotDesc.invokeReadObject(obj, this);
1920                     } catch (ClassNotFoundException ex) {
1921                         /*
1922                          * In most cases, the handle table has already
1923                          * propagated a CNFException to passHandle at this
1924                          * point; this mark call is included to address cases
1925                          * where the custom readObject method has cons'ed and
1926                          * thrown a new CNFException of its own.
1927                          */
1928                         handles.markException(passHandle, ex);
1929                     } finally {
1930                         curContext.setUsed();
1931                         curContext = oldContext;
1932                     }
1933 
1934                     /*
1935                      * defaultDataEnd may have been set indirectly by custom
1936                      * readObject() method when calling defaultReadObject() or
1937                      * readFields(); clear it to restore normal read behavior.
1938                      */
1939                     defaultDataEnd = false;
1940                 } else {
1941                     FieldValues vals = defaultReadFields(obj, slotDesc);
1942                     if (slotValues != null) {
1943                         slotValues[i] = vals;
1944                     } else if (obj != null) {
1945                         defaultCheckFieldValues(obj, slotDesc, vals);
1946                         defaultSetFieldValues(obj, slotDesc, vals);
1947                     }
1948                 }
1949                 if (slotDesc.hasWriteObjectData()) {
1950                     skipCustomData();
1951                 } else {
1952                     bin.setBlockDataMode(false);
1953                 }
1954             } else {
1955                 if (obj != null &&
1956                     slotDesc.hasReadObjectNoDataMethod() &&
1957                     handles.lookupException(passHandle) == null)
1958                 {
1959                     slotDesc.invokeReadObjectNoData(obj);
1960                 }
1961             }
1962         }
1963 
1964         if (obj != null && slotValues != null) {
1965             // Check that the non-primitive types are assignable for all slots
1966             // before assigning.
1967             for (int i = 0; i < slots.length; i++) {
1968                 if (slotValues[i] != null)
1969                     defaultCheckFieldValues(obj, slots[i].desc, slotValues[i]);
1970             }
1971             for (int i = 0; i < slots.length; i++) {
1972                 if (slotValues[i] != null)
1973                     defaultSetFieldValues(obj, slots[i].desc, slotValues[i]);
1974             }
1975         }
1976     }
1977 
1978     /**
1979      * Skips over all block data and objects until TC_ENDBLOCKDATA is
1980      * encountered.
1981      */
1982     private void skipCustomData() throws IOException {
1983         int oldHandle = passHandle;
1984         for (;;) {
1985             if (bin.getBlockDataMode()) {
1986                 bin.skipBlockData();
1987                 bin.setBlockDataMode(false);
1988             }
1989             switch (bin.peekByte()) {
1990                 case TC_BLOCKDATA:
1991                 case TC_BLOCKDATALONG:
1992                     bin.setBlockDataMode(true);
1993                     break;
1994 
1995                 case TC_ENDBLOCKDATA:
1996                     bin.readByte();
1997                     passHandle = oldHandle;
1998                     return;
1999 
2000                 default:
2001                     readObject0(false);
2002                     break;
2003             }
2004         }
2005     }
2006 
2007     private class FieldValues {
2008         final byte[] primValues;
2009         final Object[] objValues;
2010 
2011         FieldValues(byte[] primValues, Object[] objValues) {
2012             this.primValues = primValues;
2013             this.objValues = objValues;
2014         }
2015     }
2016 
2017     /**
2018      * Reads in values of serializable fields declared by given class
2019      * descriptor. Expects that passHandle is set to obj's handle before this
2020      * method is called.
2021      */
2022     private FieldValues defaultReadFields(Object obj, ObjectStreamClass desc)
2023         throws IOException
2024     {
2025         Class<?> cl = desc.forClass();
2026         if (cl != null && obj != null && !cl.isInstance(obj)) {
2027             throw new ClassCastException();
2028         }
2029 
2030         byte[] primVals = null;
2031         int primDataSize = desc.getPrimDataSize();
2032         if (primDataSize > 0) {

2033             primVals = new byte[primDataSize];

2034             bin.readFully(primVals, 0, primDataSize, false);



2035         }
2036 
2037         Object[] objVals = null;
2038         int numObjFields = desc.getNumObjFields();
2039         if (numObjFields > 0) {
2040             int objHandle = passHandle;
2041             ObjectStreamField[] fields = desc.getFields(false);
2042             objVals = new Object[numObjFields];
2043             int numPrimFields = fields.length - objVals.length;
2044             for (int i = 0; i < objVals.length; i++) {
2045                 ObjectStreamField f = fields[numPrimFields + i];
2046                 objVals[i] = readObject0(f.isUnshared());
2047                 if (f.getField() != null) {
2048                     handles.markDependency(objHandle, passHandle);
2049                 }
2050             }



2051             passHandle = objHandle;
2052         }
2053 
2054         return new FieldValues(primVals, objVals);
2055     }
2056 
2057     /** Throws ClassCastException if any value is not assignable. */
2058     private void defaultCheckFieldValues(Object obj, ObjectStreamClass desc,
2059                                          FieldValues values) {
2060         Object[] objectValues = values.objValues;
2061         if (objectValues != null)
2062             desc.checkObjFieldValueTypes(obj, objectValues);
2063     }
2064 
2065     /** Sets field values in obj. */
2066     private void defaultSetFieldValues(Object obj, ObjectStreamClass desc,
2067                                        FieldValues values) {
2068         byte[] primValues = values.primValues;
2069         Object[] objectValues = values.objValues;
2070 
2071         if (primValues != null)
2072             desc.setPrimFieldValues(obj, primValues);
2073         if (objectValues != null)
2074             desc.setObjFieldValues(obj, objectValues);
2075     }
2076 
2077     /**
2078      * Reads in and returns IOException that caused serialization to abort.
2079      * All stream state is discarded prior to reading in fatal exception.  Sets
2080      * passHandle to fatal exception's handle.
2081      */
2082     private IOException readFatalException() throws IOException {
2083         if (bin.readByte() != TC_EXCEPTION) {
2084             throw new InternalError();
2085         }
2086         clear();
2087         return (IOException) readObject0(false);
2088     }
2089 
2090     /**
2091      * If recursion depth is 0, clears internal data structures; otherwise,
2092      * throws a StreamCorruptedException.  This method is called when a
2093      * TC_RESET typecode is encountered.
2094      */