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         StreamFieldValues 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 
1886         // Best effort Failure Atomicity; Each element in 'slotFieldValues'
1887         // contains the stream field values for the same element in 'slots',
1888         // up to the first slot with a readObject(NoData) method ( a user
1889         // visible effect ).
1890         int index = 1;
1891         for (; index < slots.length; index++) {
1892             ObjectStreamClass slotDesc = slots[index].desc;
1893             if (slotDesc.hasReadObjectMethod()
1894                 || slotDesc.hasReadObjectNoDataMethod()) {
1895                 break;
1896             }
1897         }
1898         // Store, and defer setting, values for index slots, ignore if just one.
1899         StreamFieldValues[] slotFieldValues = null;
1900         if (index > 1 && obj != null)
1901             slotFieldValues =  new StreamFieldValues[index];
1902 
1903         for (int i = 0; i < slots.length; i++) {
1904             ObjectStreamClass slotDesc = slots[i].desc;
1905 
1906             if (slots[i].hasData) {
1907                 if (obj != null &&
1908                     slotDesc.hasReadObjectMethod() &&
1909                     handles.lookupException(passHandle) == null)
1910                 {
1911                     SerialCallbackContext oldContext = curContext;
1912 
1913                     try {
1914                         curContext = new SerialCallbackContext(obj, slotDesc);
1915 
1916                         bin.setBlockDataMode(true);
1917                         slotDesc.invokeReadObject(obj, this);
1918                     } catch (ClassNotFoundException ex) {
1919                         /*
1920                          * In most cases, the handle table has already
1921                          * propagated a CNFException to passHandle at this
1922                          * point; this mark call is included to address cases
1923                          * where the custom readObject method has cons'ed and
1924                          * thrown a new CNFException of its own.
1925                          */
1926                         handles.markException(passHandle, ex);
1927                     } finally {
1928                         curContext.setUsed();
1929                         curContext = oldContext;
1930                     }
1931 
1932                     /*
1933                      * defaultDataEnd may have been set indirectly by custom
1934                      * readObject() method when calling defaultReadObject() or
1935                      * readFields(); clear it to restore normal read behavior.
1936                      */
1937                     defaultDataEnd = false;
1938                 } else {
1939                     StreamFieldValues vals = defaultReadFields(obj, slotDesc);
1940                     if (obj != null)
1941                         defaultCheckFieldValues(obj, slotDesc, vals);
1942                     if (slotFieldValues != null) {
1943                         slotFieldValues[i] = vals;
1944                     } else if (obj != null) {
1945                         defaultSetFieldValues(obj, slotDesc, vals);
1946                     }
1947                 }
1948                 if (slotDesc.hasWriteObjectData()) {
1949                     skipCustomData();
1950                 } else {
1951                     bin.setBlockDataMode(false);
1952                 }
1953             } else {
1954                 if (obj != null &&
1955                     slotDesc.hasReadObjectNoDataMethod() &&
1956                     handles.lookupException(passHandle) == null)
1957                 {
1958                     slotDesc.invokeReadObjectNoData(obj);
1959                 }
1960             }
1961 
1962             if (slotFieldValues != null && i == (index - 1) && obj != null) {
1963                 assert slotFieldValues.length == index;
1964                 assert slots.length >= index;
1965                 setSlotFieldValues(obj, slots, slotFieldValues);
1966                 slotFieldValues = null;  // remaining slots will be set when read
1967             }
1968         }
1969     }
1970 
1971     /** Sets slot field values in the given obj. */
1972     private void setSlotFieldValues(Object obj,
1973                                     ObjectStreamClass.ClassDataSlot[] slots,
1974                                     StreamFieldValues[] slotFieldValues) {
1975         int length = slotFieldValues.length;
1976         for (int i = 0; i < length; i++) {
1977             if (slotFieldValues[i] != null)
1978                 defaultSetFieldValues(obj, slots[i].desc, slotFieldValues[i]);
1979         }
1980     }
1981 
1982     /**
1983      * Skips over all block data and objects until TC_ENDBLOCKDATA is
1984      * encountered.
1985      */
1986     private void skipCustomData() throws IOException {
1987         int oldHandle = passHandle;
1988         for (;;) {
1989             if (bin.getBlockDataMode()) {
1990                 bin.skipBlockData();
1991                 bin.setBlockDataMode(false);
1992             }
1993             switch (bin.peekByte()) {
1994                 case TC_BLOCKDATA:
1995                 case TC_BLOCKDATALONG:
1996                     bin.setBlockDataMode(true);
1997                     break;
1998 
1999                 case TC_ENDBLOCKDATA:
2000                     bin.readByte();
2001                     passHandle = oldHandle;
2002                     return;
2003 
2004                 default:
2005                     readObject0(false);
2006                     break;
2007             }
2008         }
2009     }
2010 
2011     /** A holder for field values read from the stream. */
2012     private class StreamFieldValues {
2013         final byte[] primValues;
2014         final Object[] objValues;
2015         StreamFieldValues(byte[] primValues, Object[] objValues) {
2016             this.primValues = primValues;
2017             this.objValues = objValues;
2018         }
2019     }
2020 
2021     /**
2022      * Reads in and returns the values of serializable fields declared by the
2023      * given class descriptor. Expects that passHandle is set to obj's handle
2024      * before this method is called.
2025      */
2026     private StreamFieldValues defaultReadFields(Object obj, ObjectStreamClass desc)
2027         throws IOException
2028     {
2029         Class<?> cl = desc.forClass();
2030         if (cl != null && obj != null && !cl.isInstance(obj)) {
2031             throw new ClassCastException();
2032         }
2033 
2034         byte[] primVals = null;
2035         int primDataSize = desc.getPrimDataSize();
2036         if (primDataSize > 0) {

2037             primVals = new byte[primDataSize];

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



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



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