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

Print this page




 235         static final ReferenceQueue<Class<?>> subclassAuditsQueue =
 236             new ReferenceQueue<>();
 237     }
 238 
 239     /** filter stream for handling block data conversion */
 240     private final BlockDataInputStream bin;
 241     /** validation callback list */
 242     private final ValidationList vlist;
 243     /** recursion depth */
 244     private int depth;
 245     /** whether stream is closed */
 246     private boolean closed;
 247 
 248     /** wire handle -> obj/exception map */
 249     private final HandleTable handles;
 250     /** scratch field for passing handle values up/down call stack */
 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


 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         defaultReadFields(curObj, curDesc);




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


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.
1903                          */
1904                         handles.markException(passHandle, ex);
1905                     } finally {
1906                         curContext.setUsed();
1907                         curContext = oldContext;
1908                     }
1909 
1910                     /*
1911                      * defaultDataEnd may have been set indirectly by custom
1912                      * readObject() method when calling defaultReadObject() or
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:
1953                     bin.readByte();
1954                     passHandle = oldHandle;
1955                     return;
1956 
1957                 default:
1958                     readObject0(false);
1959                     break;
1960             }
1961         }
1962     }
1963 










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

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

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






















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




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


 477      * this stream.  This may only be called from the readObject method of the
 478      * class being deserialized. It will throw the NotActiveException if it is
 479      * called otherwise.
 480      *
 481      * @throws  ClassNotFoundException if the class of a serialized object
 482      *          could not be found.
 483      * @throws  IOException if an I/O error occurs.
 484      * @throws  NotActiveException if the stream is not currently reading
 485      *          objects.
 486      */
 487     public void defaultReadObject()
 488         throws IOException, ClassNotFoundException
 489     {
 490         SerialCallbackContext ctx = curContext;
 491         if (ctx == null) {
 492             throw new NotActiveException("not in call to readObject");
 493         }
 494         Object curObj = ctx.getObj();
 495         ObjectStreamClass curDesc = ctx.getDesc();
 496         bin.setBlockDataMode(false);
 497         FieldValues vals = defaultReadFields(curObj, curDesc);
 498         if (curObj != null) {
 499             defaultCheckFieldValues(curObj, curDesc, vals);
 500             defaultSetFieldValues(curObj, curDesc, vals);
 501         }
 502         bin.setBlockDataMode(true);
 503         if (!curDesc.hasWriteObjectData()) {
 504             /*
 505              * Fix for 4360508: since stream does not contain terminating
 506              * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
 507              * knows to simulate end-of-custom-data behavior.
 508              */
 509             defaultDataEnd = true;
 510         }
 511         ClassNotFoundException ex = handles.lookupException(passHandle);
 512         if (ex != null) {
 513             throw ex;
 514         }
 515     }
 516 
 517     /**
 518      * Reads the persistent fields from the stream and makes them available by
 519      * name.
 520      *
 521      * @return  the <code>GetField</code> object representing the persistent


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

2030             primVals = new byte[primDataSize];

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



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



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