Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
      4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      5  *
      6  * This code is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License version 2 only, as
      8  * published by the Free Software Foundation.  Oracle designates this
      9  * particular file as subject to the "Classpath" exception as provided
     10  * by Oracle in the LICENSE file that accompanied this code.
     11  *
     12  * This code is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  * version 2 for more details (a copy is included in the LICENSE file that
     16  * accompanied this code).
     17  *
     18  * You should have received a copy of the GNU General Public License version
     19  * 2 along with this work; if not, write to the Free Software Foundation,
     20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     21  *
     22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     23  * or visit www.oracle.com if you need additional information or have any
     24  * questions.
     25  */
     26 
     27 package java.io;
     28 
     29 import java.io.ObjectStreamClass.WeakClassKey;
     30 import java.lang.ref.ReferenceQueue;
     31 import java.lang.reflect.Array;
     32 import java.lang.reflect.Modifier;
     33 import java.lang.reflect.Proxy;
     34 import java.security.AccessControlContext;
     35 import java.security.AccessController;
     36 import java.security.PrivilegedAction;
     37 import java.security.PrivilegedActionException;
     38 import java.security.PrivilegedExceptionAction;
     39 import java.util.Arrays;
     40 import java.util.HashMap;
     41 import java.util.concurrent.ConcurrentHashMap;
     42 import java.util.concurrent.ConcurrentMap;
     43 import java.util.concurrent.atomic.AtomicBoolean;
     44 import static java.io.ObjectStreamClass.processQueue;
     45 import sun.reflect.misc.ReflectUtil;
     46 import dalvik.system.VMStack;
     47 
     48 /**
     49  * An ObjectInputStream deserializes primitive data and objects previously
     50  * written using an ObjectOutputStream.
     51  *
     52  * <p>ObjectOutputStream and ObjectInputStream can provide an application with
     53  * persistent storage for graphs of objects when used with a FileOutputStream
     54  * and FileInputStream respectively.  ObjectInputStream is used to recover
     55  * those objects previously serialized. Other uses include passing objects
     56  * between hosts using a socket stream or for marshaling and unmarshaling
     57  * arguments and parameters in a remote communication system.
     58  *
     59  * <p>ObjectInputStream ensures that the types of all objects in the graph
     60  * created from the stream match the classes present in the Java Virtual
     61  * Machine.  Classes are loaded as required using the standard mechanisms.
     62  *
     63  * <p>Only objects that support the java.io.Serializable or
     64  * java.io.Externalizable interface can be read from streams.
     65  *
     66  * <p>The method <code>readObject</code> is used to read an object from the
     67  * stream.  Java's safe casting should be used to get the desired type.  In
     68  * Java, strings and arrays are objects and are treated as objects during
     69  * serialization. When read they need to be cast to the expected type.
     70  *
     71  * <p>Primitive data types can be read from the stream using the appropriate
     72  * method on DataInput.
     73  *
     74  * <p>The default deserialization mechanism for objects restores the contents
     75  * of each field to the value and type it had when it was written.  Fields
     76  * declared as transient or static are ignored by the deserialization process.
     77  * References to other objects cause those objects to be read from the stream
     78  * as necessary.  Graphs of objects are restored correctly using a reference
     79  * sharing mechanism.  New objects are always allocated when deserializing,
     80  * which prevents existing objects from being overwritten.
     81  *
     82  * <p>Reading an object is analogous to running the constructors of a new
     83  * object.  Memory is allocated for the object and initialized to zero (NULL).
     84  * No-arg constructors are invoked for the non-serializable classes and then
     85  * the fields of the serializable classes are restored from the stream starting
     86  * with the serializable class closest to java.lang.object and finishing with
     87  * the object's most specific class.
     88  *
     89  * <p>For example to read from a stream as written by the example in
     90  * ObjectOutputStream:
     91  * <br>
     92  * <pre>
     93  *      FileInputStream fis = new FileInputStream("t.tmp");
     94  *      ObjectInputStream ois = new ObjectInputStream(fis);
     95  *
     96  *      int i = ois.readInt();
     97  *      String today = (String) ois.readObject();
     98  *      Date date = (Date) ois.readObject();
     99  *
    100  *      ois.close();
    101  * </pre>
    102  *
    103  * <p>Classes control how they are serialized by implementing either the
    104  * java.io.Serializable or java.io.Externalizable interfaces.
    105  *
    106  * <p>Implementing the Serializable interface allows object serialization to
    107  * save and restore the entire state of the object and it allows classes to
    108  * evolve between the time the stream is written and the time it is read.  It
    109  * automatically traverses references between objects, saving and restoring
    110  * entire graphs.
    111  *
    112  * <p>Serializable classes that require special handling during the
    113  * serialization and deserialization process should implement the following
    114  * methods:
    115  *
    116  * <pre>
    117  * private void writeObject(java.io.ObjectOutputStream stream)
    118  *     throws IOException;
    119  * private void readObject(java.io.ObjectInputStream stream)
    120  *     throws IOException, ClassNotFoundException;
    121  * private void readObjectNoData()
    122  *     throws ObjectStreamException;
    123  * </pre>
    124  *
    125  * <p>The readObject method is responsible for reading and restoring the state
    126  * of the object for its particular class using data written to the stream by
    127  * the corresponding writeObject method.  The method does not need to concern
    128  * itself with the state belonging to its superclasses or subclasses.  State is
    129  * restored by reading data from the ObjectInputStream for the individual
    130  * fields and making assignments to the appropriate fields of the object.
    131  * Reading primitive data types is supported by DataInput.
    132  *
    133  * <p>Any attempt to read object data which exceeds the boundaries of the
    134  * custom data written by the corresponding writeObject method will cause an
    135  * OptionalDataException to be thrown with an eof field value of true.
    136  * Non-object reads which exceed the end of the allotted data will reflect the
    137  * end of data in the same way that they would indicate the end of the stream:
    138  * bytewise reads will return -1 as the byte read or number of bytes read, and
    139  * primitive reads will throw EOFExceptions.  If there is no corresponding
    140  * writeObject method, then the end of default serialized data marks the end of
    141  * the allotted data.
    142  *
    143  * <p>Primitive and object read calls issued from within a readExternal method
    144  * behave in the same manner--if the stream is already positioned at the end of
    145  * data written by the corresponding writeExternal method, object reads will
    146  * throw OptionalDataExceptions with eof set to true, bytewise reads will
    147  * return -1, and primitive reads will throw EOFExceptions.  Note that this
    148  * behavior does not hold for streams written with the old
    149  * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
    150  * end of data written by writeExternal methods is not demarcated, and hence
    151  * cannot be detected.
    152  *
    153  * <p>The readObjectNoData method is responsible for initializing the state of
    154  * the object for its particular class in the event that the serialization
    155  * stream does not list the given class as a superclass of the object being
    156  * deserialized.  This may occur in cases where the receiving party uses a
    157  * different version of the deserialized instance's class than the sending
    158  * party, and the receiver's version extends classes that are not extended by
    159  * the sender's version.  This may also occur if the serialization stream has
    160  * been tampered; hence, readObjectNoData is useful for initializing
    161  * deserialized objects properly despite a "hostile" or incomplete source
    162  * stream.
    163  *
    164  * <p>Serialization does not read or assign values to the fields of any object
    165  * that does not implement the java.io.Serializable interface.  Subclasses of
    166  * Objects that are not serializable can be serializable. In this case the
    167  * non-serializable class must have a no-arg constructor to allow its fields to
    168  * be initialized.  In this case it is the responsibility of the subclass to
    169  * save and restore the state of the non-serializable class. It is frequently
    170  * the case that the fields of that class are accessible (public, package, or
    171  * protected) or that there are get and set methods that can be used to restore
    172  * the state.
    173  *
    174  * <p>Any exception that occurs while deserializing an object will be caught by
    175  * the ObjectInputStream and abort the reading process.
    176  *
    177  * <p>Implementing the Externalizable interface allows the object to assume
    178  * complete control over the contents and format of the object's serialized
    179  * form.  The methods of the Externalizable interface, writeExternal and
    180  * readExternal, are called to save and restore the objects state.  When
    181  * implemented by a class they can write and read their own state using all of
    182  * the methods of ObjectOutput and ObjectInput.  It is the responsibility of
    183  * the objects to handle any versioning that occurs.
    184  *
    185  * <p>Enum constants are deserialized differently than ordinary serializable or
    186  * externalizable objects.  The serialized form of an enum constant consists
    187  * solely of its name; field values of the constant are not transmitted.  To
    188  * deserialize an enum constant, ObjectInputStream reads the constant name from
    189  * the stream; the deserialized constant is then obtained by calling the static
    190  * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
    191  * base type and the received constant name as arguments.  Like other
    192  * serializable or externalizable objects, enum constants can function as the
    193  * targets of back references appearing subsequently in the serialization
    194  * stream.  The process by which enum constants are deserialized cannot be
    195  * customized: any class-specific readObject, readObjectNoData, and readResolve
    196  * methods defined by enum types are ignored during deserialization.
    197  * Similarly, any serialPersistentFields or serialVersionUID field declarations
    198  * are also ignored--all enum types have a fixed serialVersionUID of 0L.
    199  *
    200  * @author      Mike Warres
    201  * @author      Roger Riggs
    202  * @see java.io.DataInput
    203  * @see java.io.ObjectOutputStream
    204  * @see java.io.Serializable
    205  * @see <a href="{@docRoot}openjdk-redirect.html?v=8&path=/platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
    206  * @since   JDK1.1
    207  */
    208 public class ObjectInputStream
    209     extends InputStream implements ObjectInput, ObjectStreamConstants
    210 {
    211     /** handle value representing null */
    212     private static final int NULL_HANDLE = -1;
    213 
    214     /** marker for unshared objects in internal handle table */
    215     private static final Object unsharedMarker = new Object();
    216 
    217     /** table mapping primitive type names to corresponding class objects */
    218     private static final HashMap<String, Class<?>> primClasses
    219         = new HashMap<>(8, 1.0F);
    220     static {
    221         primClasses.put("boolean", boolean.class);
    222         primClasses.put("byte", byte.class);
    223         primClasses.put("char", char.class);
    224         primClasses.put("short", short.class);
    225         primClasses.put("int", int.class);
    226         primClasses.put("long", long.class);
    227         primClasses.put("float", float.class);
    228         primClasses.put("double", double.class);
    229         primClasses.put("void", void.class);
    230     }
    231 
    232     private static class Caches {
    233         /** cache of subclass security audit results */
    234         static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
    235             new ConcurrentHashMap<>();
    236 
    237         /** queue for WeakReferences to audited subclasses */
    238         static final ReferenceQueue<Class<?>> subclassAuditsQueue =
    239             new ReferenceQueue<>();
    240     }
    241 
    242     /** filter stream for handling block data conversion */
    243     private final BlockDataInputStream bin;
    244     /** validation callback list */
    245     private final ValidationList vlist;
    246     /** recursion depth */
    247     private int depth;
    248     /** whether stream is closed */
    249     private boolean closed;
    250 
    251     /** wire handle -> obj/exception map */
    252     private final HandleTable handles;
    253     /** scratch field for passing handle values up/down call stack */
    254     private int passHandle = NULL_HANDLE;
    255     /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
    256     private boolean defaultDataEnd = false;
    257 
    258     /** buffer for reading primitive field values */
    259     private byte[] primVals;
    260 
    261     /** if true, invoke readObjectOverride() instead of readObject() */
    262     private final boolean enableOverride;
    263     /** if true, invoke resolveObject() */
    264     private boolean enableResolve;
    265 
    266     /**
    267      * Context during upcalls to class-defined readObject methods; holds
    268      * object currently being deserialized and descriptor for current class.
    269      * Null when not during readObject upcall.
    270      */
    271     private SerialCallbackContext curContext;
    272 
    273     /**
    274      * Creates an ObjectInputStream that reads from the specified InputStream.
    275      * A serialization stream header is read from the stream and verified.
    276      * This constructor will block until the corresponding ObjectOutputStream
    277      * has written and flushed the header.
    278      *
    279      * <p>If a security manager is installed, this constructor will check for
    280      * the "enableSubclassImplementation" SerializablePermission when invoked
    281      * directly or indirectly by the constructor of a subclass which overrides
    282      * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
    283      * methods.
    284      *
    285      * @param   in input stream to read from
    286      * @throws  StreamCorruptedException if the stream header is incorrect
    287      * @throws  IOException if an I/O error occurs while reading stream header
    288      * @throws  SecurityException if untrusted subclass illegally overrides
    289      *          security-sensitive methods
    290      * @throws  NullPointerException if <code>in</code> is <code>null</code>
    291      * @see     ObjectInputStream#ObjectInputStream()
    292      * @see     ObjectInputStream#readFields()
    293      * @see     ObjectOutputStream#ObjectOutputStream(OutputStream)
    294      */
    295     public ObjectInputStream(InputStream in) throws IOException {
    296         verifySubclass();
    297         bin = new BlockDataInputStream(in);
    298         handles = new HandleTable(10);
    299         vlist = new ValidationList();
    300         enableOverride = false;
    301         readStreamHeader();
    302         bin.setBlockDataMode(true);
    303     }
    304 
    305     /**
    306      * Provide a way for subclasses that are completely reimplementing
    307      * ObjectInputStream to not have to allocate private data just used by this
    308      * implementation of ObjectInputStream.
    309      *
    310      * <p>If there is a security manager installed, this method first calls the
    311      * security manager's <code>checkPermission</code> method with the
    312      * <code>SerializablePermission("enableSubclassImplementation")</code>
    313      * permission to ensure it's ok to enable subclassing.
    314      *
    315      * @throws  SecurityException if a security manager exists and its
    316      *          <code>checkPermission</code> method denies enabling
    317      *          subclassing.
    318      * @throws  IOException if an I/O error occurs while creating this stream
    319      * @see SecurityManager#checkPermission
    320      * @see java.io.SerializablePermission
    321      */
    322     protected ObjectInputStream() throws IOException, SecurityException {
    323         SecurityManager sm = System.getSecurityManager();
    324         if (sm != null) {
    325             sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
    326         }
    327         bin = null;
    328         handles = null;
    329         vlist = null;
    330         enableOverride = true;
    331     }
    332 
    333     /**
    334      * Read an object from the ObjectInputStream.  The class of the object, the
    335      * signature of the class, and the values of the non-transient and
    336      * non-static fields of the class and all of its supertypes are read.
    337      * Default deserializing for a class can be overriden using the writeObject
    338      * and readObject methods.  Objects referenced by this object are read
    339      * transitively so that a complete equivalent graph of objects is
    340      * reconstructed by readObject.
    341      *
    342      * <p>The root object is completely restored when all of its fields and the
    343      * objects it references are completely restored.  At this point the object
    344      * validation callbacks are executed in order based on their registered
    345      * priorities. The callbacks are registered by objects (in the readObject
    346      * special methods) as they are individually restored.
    347      *
    348      * <p>Exceptions are thrown for problems with the InputStream and for
    349      * classes that should not be deserialized.  All exceptions are fatal to
    350      * the InputStream and leave it in an indeterminate state; it is up to the
    351      * caller to ignore or recover the stream state.
    352      *
    353      * @throws  ClassNotFoundException Class of a serialized object cannot be
    354      *          found.
    355      * @throws  InvalidClassException Something is wrong with a class used by
    356      *          serialization.
    357      * @throws  StreamCorruptedException Control information in the
    358      *          stream is inconsistent.
    359      * @throws  OptionalDataException Primitive data was found in the
    360      *          stream instead of objects.
    361      * @throws  IOException Any of the usual Input/Output related exceptions.
    362      */
    363     public final Object readObject()
    364         throws IOException, ClassNotFoundException
    365     {
    366         if (enableOverride) {
    367             return readObjectOverride();
    368         }
    369 
    370         // if nested read, passHandle contains handle of enclosing object
    371         int outerHandle = passHandle;
    372         try {
    373             Object obj = readObject0(false);
    374             handles.markDependency(outerHandle, passHandle);
    375             ClassNotFoundException ex = handles.lookupException(passHandle);
    376             if (ex != null) {
    377                 throw ex;
    378             }
    379             if (depth == 0) {
    380                 vlist.doCallbacks();
    381             }
    382             return obj;
    383         } finally {
    384             passHandle = outerHandle;
    385             if (closed && depth == 0) {
    386                 clear();
    387             }
    388         }
    389     }
    390 
    391     /**
    392      * This method is called by trusted subclasses of ObjectOutputStream that
    393      * constructed ObjectOutputStream using the protected no-arg constructor.
    394      * The subclass is expected to provide an override method with the modifier
    395      * "final".
    396      *
    397      * @return  the Object read from the stream.
    398      * @throws  ClassNotFoundException Class definition of a serialized object
    399      *          cannot be found.
    400      * @throws  OptionalDataException Primitive data was found in the stream
    401      *          instead of objects.
    402      * @throws  IOException if I/O errors occurred while reading from the
    403      *          underlying stream
    404      * @see #ObjectInputStream()
    405      * @see #readObject()
    406      * @since 1.2
    407      */
    408     protected Object readObjectOverride()
    409         throws IOException, ClassNotFoundException
    410     {
    411         return null;
    412     }
    413 
    414     /**
    415      * Reads an "unshared" object from the ObjectInputStream.  This method is
    416      * identical to readObject, except that it prevents subsequent calls to
    417      * readObject and readUnshared from returning additional references to the
    418      * deserialized instance obtained via this call.  Specifically:
    419      * <ul>
    420      *   <li>If readUnshared is called to deserialize a back-reference (the
    421      *       stream representation of an object which has been written
    422      *       previously to the stream), an ObjectStreamException will be
    423      *       thrown.
    424      *
    425      *   <li>If readUnshared returns successfully, then any subsequent attempts
    426      *       to deserialize back-references to the stream handle deserialized
    427      *       by readUnshared will cause an ObjectStreamException to be thrown.
    428      * </ul>
    429      * Deserializing an object via readUnshared invalidates the stream handle
    430      * associated with the returned object.  Note that this in itself does not
    431      * always guarantee that the reference returned by readUnshared is unique;
    432      * the deserialized object may define a readResolve method which returns an
    433      * object visible to other parties, or readUnshared may return a Class
    434      * object or enum constant obtainable elsewhere in the stream or through
    435      * external means. If the deserialized object defines a readResolve method
    436      * and the invocation of that method returns an array, then readUnshared
    437      * returns a shallow clone of that array; this guarantees that the returned
    438      * array object is unique and cannot be obtained a second time from an
    439      * invocation of readObject or readUnshared on the ObjectInputStream,
    440      * even if the underlying data stream has been manipulated.
    441      *
    442      * <p>ObjectInputStream subclasses which override this method can only be
    443      * constructed in security contexts possessing the
    444      * "enableSubclassImplementation" SerializablePermission; any attempt to
    445      * instantiate such a subclass without this permission will cause a
    446      * SecurityException to be thrown.
    447      *
    448      * @return  reference to deserialized object
    449      * @throws  ClassNotFoundException if class of an object to deserialize
    450      *          cannot be found
    451      * @throws  StreamCorruptedException if control information in the stream
    452      *          is inconsistent
    453      * @throws  ObjectStreamException if object to deserialize has already
    454      *          appeared in stream
    455      * @throws  OptionalDataException if primitive data is next in stream
    456      * @throws  IOException if an I/O error occurs during deserialization
    457      * @since   1.4
    458      */
    459     public Object readUnshared() throws IOException, ClassNotFoundException {
    460         // if nested read, passHandle contains handle of enclosing object
    461         int outerHandle = passHandle;
    462         try {
    463             Object obj = readObject0(true);
    464             handles.markDependency(outerHandle, passHandle);
    465             ClassNotFoundException ex = handles.lookupException(passHandle);
    466             if (ex != null) {
    467                 throw ex;
    468             }
    469             if (depth == 0) {
    470                 vlist.doCallbacks();
    471             }
    472             return obj;
    473         } finally {
    474             passHandle = outerHandle;
    475             if (closed && depth == 0) {
    476                 clear();
    477             }
    478         }
    479     }
    480 
    481     /**
    482      * Read the non-static and non-transient fields of the current class from
    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
    524      *          fields of the object being deserialized
    525      * @throws  ClassNotFoundException if the class of a serialized object
    526      *          could not be found.
    527      * @throws  IOException if an I/O error occurs.
    528      * @throws  NotActiveException if the stream is not currently reading
    529      *          objects.
    530      * @since 1.2
    531      */
    532     public ObjectInputStream.GetField readFields()
    533         throws IOException, ClassNotFoundException
    534     {
    535         SerialCallbackContext ctx = curContext;
    536         if (ctx == null) {
    537             throw new NotActiveException("not in call to readObject");
    538         }
    539         Object curObj = ctx.getObj();
    540         ObjectStreamClass curDesc = ctx.getDesc();
    541         bin.setBlockDataMode(false);
    542         GetFieldImpl getField = new GetFieldImpl(curDesc);
    543         getField.readFields();
    544         bin.setBlockDataMode(true);
    545         if (!curDesc.hasWriteObjectData()) {
    546             /*
    547              * Fix for 4360508: since stream does not contain terminating
    548              * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
    549              * knows to simulate end-of-custom-data behavior.
    550              */
    551             defaultDataEnd = true;
    552         }
    553 
    554         return getField;
    555     }
    556 
    557     /**
    558      * Register an object to be validated before the graph is returned.  While
    559      * similar to resolveObject these validations are called after the entire
    560      * graph has been reconstituted.  Typically, a readObject method will
    561      * register the object with the stream so that when all of the objects are
    562      * restored a final set of validations can be performed.
    563      *
    564      * @param   obj the object to receive the validation callback.
    565      * @param   prio controls the order of callbacks;zero is a good default.
    566      *          Use higher numbers to be called back earlier, lower numbers for
    567      *          later callbacks. Within a priority, callbacks are processed in
    568      *          no particular order.
    569      * @throws  NotActiveException The stream is not currently reading objects
    570      *          so it is invalid to register a callback.
    571      * @throws  InvalidObjectException The validation object is null.
    572      */
    573     public void registerValidation(ObjectInputValidation obj, int prio)
    574         throws NotActiveException, InvalidObjectException
    575     {
    576         if (depth == 0) {
    577             throw new NotActiveException("stream inactive");
    578         }
    579         vlist.register(obj, prio);
    580     }
    581 
    582     /**
    583      * Load the local class equivalent of the specified stream class
    584      * description.  Subclasses may implement this method to allow classes to
    585      * be fetched from an alternate source.
    586      *
    587      * <p>The corresponding method in <code>ObjectOutputStream</code> is
    588      * <code>annotateClass</code>.  This method will be invoked only once for
    589      * each unique class in the stream.  This method can be implemented by
    590      * subclasses to use an alternate loading mechanism but must return a
    591      * <code>Class</code> object. Once returned, if the class is not an array
    592      * class, its serialVersionUID is compared to the serialVersionUID of the
    593      * serialized class, and if there is a mismatch, the deserialization fails
    594      * and an {@link InvalidClassException} is thrown.
    595      *
    596      * <p>The default implementation of this method in
    597      * <code>ObjectInputStream</code> returns the result of calling
    598      * <pre>
    599      *     Class.forName(desc.getName(), false, loader)
    600      * </pre>
    601      * where <code>loader</code> is determined as follows: if there is a
    602      * method on the current thread's stack whose declaring class was
    603      * defined by a user-defined class loader (and was not a generated to
    604      * implement reflective invocations), then <code>loader</code> is class
    605      * loader corresponding to the closest such method to the currently
    606      * executing frame; otherwise, <code>loader</code> is
    607      * <code>null</code>. If this call results in a
    608      * <code>ClassNotFoundException</code> and the name of the passed
    609      * <code>ObjectStreamClass</code> instance is the Java language keyword
    610      * for a primitive type or void, then the <code>Class</code> object
    611      * representing that primitive type or void will be returned
    612      * (e.g., an <code>ObjectStreamClass</code> with the name
    613      * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
    614      * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
    615      * the caller of this method.
    616      *
    617      * @param   desc an instance of class <code>ObjectStreamClass</code>
    618      * @return  a <code>Class</code> object corresponding to <code>desc</code>
    619      * @throws  IOException any of the usual Input/Output exceptions.
    620      * @throws  ClassNotFoundException if class of a serialized object cannot
    621      *          be found.
    622      */
    623     protected Class<?> resolveClass(ObjectStreamClass desc)
    624         throws IOException, ClassNotFoundException
    625     {
    626         String name = desc.getName();
    627         try {
    628             return Class.forName(name, false, latestUserDefinedLoader());
    629         } catch (ClassNotFoundException ex) {
    630             Class<?> cl = primClasses.get(name);
    631             if (cl != null) {
    632                 return cl;
    633             } else {
    634                 throw ex;
    635             }
    636         }
    637     }
    638 
    639     /**
    640      * Returns a proxy class that implements the interfaces named in a proxy
    641      * class descriptor; subclasses may implement this method to read custom
    642      * data from the stream along with the descriptors for dynamic proxy
    643      * classes, allowing them to use an alternate loading mechanism for the
    644      * interfaces and the proxy class.
    645      *
    646      * <p>This method is called exactly once for each unique proxy class
    647      * descriptor in the stream.
    648      *
    649      * <p>The corresponding method in <code>ObjectOutputStream</code> is
    650      * <code>annotateProxyClass</code>.  For a given subclass of
    651      * <code>ObjectInputStream</code> that overrides this method, the
    652      * <code>annotateProxyClass</code> method in the corresponding subclass of
    653      * <code>ObjectOutputStream</code> must write any data or objects read by
    654      * this method.
    655      *
    656      * <p>The default implementation of this method in
    657      * <code>ObjectInputStream</code> returns the result of calling
    658      * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
    659      * objects for the interfaces that are named in the <code>interfaces</code>
    660      * parameter.  The <code>Class</code> object for each interface name
    661      * <code>i</code> is the value returned by calling
    662      * <pre>
    663      *     Class.forName(i, false, loader)
    664      * </pre>
    665      * where <code>loader</code> is that of the first non-<code>null</code>
    666      * class loader up the execution stack, or <code>null</code> if no
    667      * non-<code>null</code> class loaders are on the stack (the same class
    668      * loader choice used by the <code>resolveClass</code> method).  Unless any
    669      * of the resolved interfaces are non-public, this same value of
    670      * <code>loader</code> is also the class loader passed to
    671      * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
    672      * their class loader is passed instead (if more than one non-public
    673      * interface class loader is encountered, an
    674      * <code>IllegalAccessError</code> is thrown).
    675      * If <code>Proxy.getProxyClass</code> throws an
    676      * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
    677      * will throw a <code>ClassNotFoundException</code> containing the
    678      * <code>IllegalArgumentException</code>.
    679      *
    680      * @param interfaces the list of interface names that were
    681      *                deserialized in the proxy class descriptor
    682      * @return  a proxy class for the specified interfaces
    683      * @throws        IOException any exception thrown by the underlying
    684      *                <code>InputStream</code>
    685      * @throws        ClassNotFoundException if the proxy class or any of the
    686      *                named interfaces could not be found
    687      * @see ObjectOutputStream#annotateProxyClass(Class)
    688      * @since 1.3
    689      */
    690     protected Class<?> resolveProxyClass(String[] interfaces)
    691         throws IOException, ClassNotFoundException
    692     {
    693         ClassLoader latestLoader = latestUserDefinedLoader();
    694         ClassLoader nonPublicLoader = null;
    695         boolean hasNonPublicInterface = false;
    696 
    697         // define proxy in class loader of non-public interface(s), if any
    698         Class<?>[] classObjs = new Class<?>[interfaces.length];
    699         for (int i = 0; i < interfaces.length; i++) {
    700             Class<?> cl = Class.forName(interfaces[i], false, latestLoader);
    701             if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
    702                 if (hasNonPublicInterface) {
    703                     if (nonPublicLoader != cl.getClassLoader()) {
    704                         throw new IllegalAccessError(
    705                             "conflicting non-public interface class loaders");
    706                     }
    707                 } else {
    708                     nonPublicLoader = cl.getClassLoader();
    709                     hasNonPublicInterface = true;
    710                 }
    711             }
    712             classObjs[i] = cl;
    713         }
    714         try {
    715             return Proxy.getProxyClass(
    716                 hasNonPublicInterface ? nonPublicLoader : latestLoader,
    717                 classObjs);
    718         } catch (IllegalArgumentException e) {
    719             throw new ClassNotFoundException(null, e);
    720         }
    721     }
    722 
    723     /**
    724      * This method will allow trusted subclasses of ObjectInputStream to
    725      * substitute one object for another during deserialization. Replacing
    726      * objects is disabled until enableResolveObject is called. The
    727      * enableResolveObject method checks that the stream requesting to resolve
    728      * object can be trusted. Every reference to serializable objects is passed
    729      * to resolveObject.  To insure that the private state of objects is not
    730      * unintentionally exposed only trusted streams may use resolveObject.
    731      *
    732      * <p>This method is called after an object has been read but before it is
    733      * returned from readObject.  The default resolveObject method just returns
    734      * the same object.
    735      *
    736      * <p>When a subclass is replacing objects it must insure that the
    737      * substituted object is compatible with every field where the reference
    738      * will be stored.  Objects whose type is not a subclass of the type of the
    739      * field or array element abort the serialization by raising an exception
    740      * and the object is not be stored.
    741      *
    742      * <p>This method is called only once when each object is first
    743      * encountered.  All subsequent references to the object will be redirected
    744      * to the new object.
    745      *
    746      * @param   obj object to be substituted
    747      * @return  the substituted object
    748      * @throws  IOException Any of the usual Input/Output exceptions.
    749      */
    750     protected Object resolveObject(Object obj) throws IOException {
    751         return obj;
    752     }
    753 
    754     /**
    755      * Enable the stream to allow objects read from the stream to be replaced.
    756      * When enabled, the resolveObject method is called for every object being
    757      * deserialized.
    758      *
    759      * <p>If <i>enable</i> is true, and there is a security manager installed,
    760      * this method first calls the security manager's
    761      * <code>checkPermission</code> method with the
    762      * <code>SerializablePermission("enableSubstitution")</code> permission to
    763      * ensure it's ok to enable the stream to allow objects read from the
    764      * stream to be replaced.
    765      *
    766      * @param   enable true for enabling use of <code>resolveObject</code> for
    767      *          every object being deserialized
    768      * @return  the previous setting before this method was invoked
    769      * @throws  SecurityException if a security manager exists and its
    770      *          <code>checkPermission</code> method denies enabling the stream
    771      *          to allow objects read from the stream to be replaced.
    772      * @see SecurityManager#checkPermission
    773      * @see java.io.SerializablePermission
    774      */
    775     protected boolean enableResolveObject(boolean enable)
    776         throws SecurityException
    777     {
    778         if (enable == enableResolve) {
    779             return enable;
    780         }
    781         if (enable) {
    782             SecurityManager sm = System.getSecurityManager();
    783             if (sm != null) {
    784                 sm.checkPermission(SUBSTITUTION_PERMISSION);
    785             }
    786         }
    787         enableResolve = enable;
    788         return !enableResolve;
    789     }
    790 
    791     /**
    792      * The readStreamHeader method is provided to allow subclasses to read and
    793      * verify their own stream headers. It reads and verifies the magic number
    794      * and version number.
    795      *
    796      * @throws  IOException if there are I/O errors while reading from the
    797      *          underlying <code>InputStream</code>
    798      * @throws  StreamCorruptedException if control information in the stream
    799      *          is inconsistent
    800      */
    801     protected void readStreamHeader()
    802         throws IOException, StreamCorruptedException
    803     {
    804         short s0 = bin.readShort();
    805         short s1 = bin.readShort();
    806         if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
    807             throw new StreamCorruptedException(
    808                 String.format("invalid stream header: %04X%04X", s0, s1));
    809         }
    810     }
    811 
    812     /**
    813      * Read a class descriptor from the serialization stream.  This method is
    814      * called when the ObjectInputStream expects a class descriptor as the next
    815      * item in the serialization stream.  Subclasses of ObjectInputStream may
    816      * override this method to read in class descriptors that have been written
    817      * in non-standard formats (by subclasses of ObjectOutputStream which have
    818      * overridden the <code>writeClassDescriptor</code> method).  By default,
    819      * this method reads class descriptors according to the format defined in
    820      * the Object Serialization specification.
    821      *
    822      * @return  the class descriptor read
    823      * @throws  IOException If an I/O error has occurred.
    824      * @throws  ClassNotFoundException If the Class of a serialized object used
    825      *          in the class descriptor representation cannot be found
    826      * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
    827      * @since 1.3
    828      */
    829     protected ObjectStreamClass readClassDescriptor()
    830         throws IOException, ClassNotFoundException
    831     {
    832         ObjectStreamClass desc = new ObjectStreamClass();
    833         desc.readNonProxy(this);
    834         return desc;
    835     }
    836 
    837     /**
    838      * Reads a byte of data. This method will block if no input is available.
    839      *
    840      * @return  the byte read, or -1 if the end of the stream is reached.
    841      * @throws  IOException If an I/O error has occurred.
    842      */
    843     public int read() throws IOException {
    844         return bin.read();
    845     }
    846 
    847     /**
    848      * Reads into an array of bytes.  This method will block until some input
    849      * is available. Consider using java.io.DataInputStream.readFully to read
    850      * exactly 'length' bytes.
    851      *
    852      * @param   buf the buffer into which the data is read
    853      * @param   off the start offset of the data
    854      * @param   len the maximum number of bytes read
    855      * @return  the actual number of bytes read, -1 is returned when the end of
    856      *          the stream is reached.
    857      * @throws  IOException If an I/O error has occurred.
    858      * @see java.io.DataInputStream#readFully(byte[],int,int)
    859      */
    860     public int read(byte[] buf, int off, int len) throws IOException {
    861         if (buf == null) {
    862             throw new NullPointerException();
    863         }
    864         int endoff = off + len;
    865         if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
    866             throw new IndexOutOfBoundsException();
    867         }
    868         return bin.read(buf, off, len, false);
    869     }
    870 
    871     /**
    872      * Returns the number of bytes that can be read without blocking.
    873      *
    874      * @return  the number of available bytes.
    875      * @throws  IOException if there are I/O errors while reading from the
    876      *          underlying <code>InputStream</code>
    877      */
    878     public int available() throws IOException {
    879         return bin.available();
    880     }
    881 
    882     /**
    883      * Closes the input stream. Must be called to release any resources
    884      * associated with the stream.
    885      *
    886      * @throws  IOException If an I/O error has occurred.
    887      */
    888     public void close() throws IOException {
    889         /*
    890          * Even if stream already closed, propagate redundant close to
    891          * underlying stream to stay consistent with previous implementations.
    892          */
    893         closed = true;
    894         if (depth == 0) {
    895             clear();
    896         }
    897         bin.close();
    898     }
    899 
    900     /**
    901      * Reads in a boolean.
    902      *
    903      * @return  the boolean read.
    904      * @throws  EOFException If end of file is reached.
    905      * @throws  IOException If other I/O error has occurred.
    906      */
    907     public boolean readBoolean() throws IOException {
    908         return bin.readBoolean();
    909     }
    910 
    911     /**
    912      * Reads an 8 bit byte.
    913      *
    914      * @return  the 8 bit byte read.
    915      * @throws  EOFException If end of file is reached.
    916      * @throws  IOException If other I/O error has occurred.
    917      */
    918     public byte readByte() throws IOException  {
    919         return bin.readByte();
    920     }
    921 
    922     /**
    923      * Reads an unsigned 8 bit byte.
    924      *
    925      * @return  the 8 bit byte read.
    926      * @throws  EOFException If end of file is reached.
    927      * @throws  IOException If other I/O error has occurred.
    928      */
    929     public int readUnsignedByte()  throws IOException {
    930         return bin.readUnsignedByte();
    931     }
    932 
    933     /**
    934      * Reads a 16 bit char.
    935      *
    936      * @return  the 16 bit char read.
    937      * @throws  EOFException If end of file is reached.
    938      * @throws  IOException If other I/O error has occurred.
    939      */
    940     public char readChar()  throws IOException {
    941         return bin.readChar();
    942     }
    943 
    944     /**
    945      * Reads a 16 bit short.
    946      *
    947      * @return  the 16 bit short read.
    948      * @throws  EOFException If end of file is reached.
    949      * @throws  IOException If other I/O error has occurred.
    950      */
    951     public short readShort()  throws IOException {
    952         return bin.readShort();
    953     }
    954 
    955     /**
    956      * Reads an unsigned 16 bit short.
    957      *
    958      * @return  the 16 bit short read.
    959      * @throws  EOFException If end of file is reached.
    960      * @throws  IOException If other I/O error has occurred.
    961      */
    962     public int readUnsignedShort() throws IOException {
    963         return bin.readUnsignedShort();
    964     }
    965 
    966     /**
    967      * Reads a 32 bit int.
    968      *
    969      * @return  the 32 bit integer read.
    970      * @throws  EOFException If end of file is reached.
    971      * @throws  IOException If other I/O error has occurred.
    972      */
    973     public int readInt()  throws IOException {
    974         return bin.readInt();
    975     }
    976 
    977     /**
    978      * Reads a 64 bit long.
    979      *
    980      * @return  the read 64 bit long.
    981      * @throws  EOFException If end of file is reached.
    982      * @throws  IOException If other I/O error has occurred.
    983      */
    984     public long readLong()  throws IOException {
    985         return bin.readLong();
    986     }
    987 
    988     /**
    989      * Reads a 32 bit float.
    990      *
    991      * @return  the 32 bit float read.
    992      * @throws  EOFException If end of file is reached.
    993      * @throws  IOException If other I/O error has occurred.
    994      */
    995     public float readFloat() throws IOException {
    996         return bin.readFloat();
    997     }
    998 
    999     /**
   1000      * Reads a 64 bit double.
   1001      *
   1002      * @return  the 64 bit double read.
   1003      * @throws  EOFException If end of file is reached.
   1004      * @throws  IOException If other I/O error has occurred.
   1005      */
   1006     public double readDouble() throws IOException {
   1007         return bin.readDouble();
   1008     }
   1009 
   1010     /**
   1011      * Reads bytes, blocking until all bytes are read.
   1012      *
   1013      * @param   buf the buffer into which the data is read
   1014      * @throws  EOFException If end of file is reached.
   1015      * @throws  IOException If other I/O error has occurred.
   1016      */
   1017     public void readFully(byte[] buf) throws IOException {
   1018         bin.readFully(buf, 0, buf.length, false);
   1019     }
   1020 
   1021     /**
   1022      * Reads bytes, blocking until all bytes are read.
   1023      *
   1024      * @param   buf the buffer into which the data is read
   1025      * @param   off the start offset of the data
   1026      * @param   len the maximum number of bytes to read
   1027      * @throws  EOFException If end of file is reached.
   1028      * @throws  IOException If other I/O error has occurred.
   1029      */
   1030     public void readFully(byte[] buf, int off, int len) throws IOException {
   1031         int endoff = off + len;
   1032         if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
   1033             throw new IndexOutOfBoundsException();
   1034         }
   1035         bin.readFully(buf, off, len, false);
   1036     }
   1037 
   1038     /**
   1039      * Skips bytes.
   1040      *
   1041      * @param   len the number of bytes to be skipped
   1042      * @return  the actual number of bytes skipped.
   1043      * @throws  IOException If an I/O error has occurred.
   1044      */
   1045     public int skipBytes(int len) throws IOException {
   1046         return bin.skipBytes(len);
   1047     }
   1048 
   1049     /**
   1050      * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
   1051      *
   1052      * @return  a String copy of the line.
   1053      * @throws  IOException if there are I/O errors while reading from the
   1054      *          underlying <code>InputStream</code>
   1055      * @deprecated This method does not properly convert bytes to characters.
   1056      *          see DataInputStream for the details and alternatives.
   1057      */
   1058     @Deprecated
   1059     public String readLine() throws IOException {
   1060         return bin.readLine();
   1061     }
   1062 
   1063     /**
   1064      * Reads a String in
   1065      * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
   1066      * format.
   1067      *
   1068      * @return  the String.
   1069      * @throws  IOException if there are I/O errors while reading from the
   1070      *          underlying <code>InputStream</code>
   1071      * @throws  UTFDataFormatException if read bytes do not represent a valid
   1072      *          modified UTF-8 encoding of a string
   1073      */
   1074     public String readUTF() throws IOException {
   1075         return bin.readUTF();
   1076     }
   1077 
   1078     /**
   1079      * Provide access to the persistent fields read from the input stream.
   1080      */
   1081     public static abstract class GetField {
   1082 
   1083         /**
   1084          * Get the ObjectStreamClass that describes the fields in the stream.
   1085          *
   1086          * @return  the descriptor class that describes the serializable fields
   1087          */
   1088         public abstract ObjectStreamClass getObjectStreamClass();
   1089 
   1090         /**
   1091          * Return true if the named field is defaulted and has no value in this
   1092          * stream.
   1093          *
   1094          * @param  name the name of the field
   1095          * @return true, if and only if the named field is defaulted
   1096          * @throws IOException if there are I/O errors while reading from
   1097          *         the underlying <code>InputStream</code>
   1098          * @throws IllegalArgumentException if <code>name</code> does not
   1099          *         correspond to a serializable field
   1100          */
   1101         public abstract boolean defaulted(String name) throws IOException;
   1102 
   1103         /**
   1104          * Get the value of the named boolean field from the persistent field.
   1105          *
   1106          * @param  name the name of the field
   1107          * @param  val the default value to use if <code>name</code> does not
   1108          *         have a value
   1109          * @return the value of the named <code>boolean</code> field
   1110          * @throws IOException if there are I/O errors while reading from the
   1111          *         underlying <code>InputStream</code>
   1112          * @throws IllegalArgumentException if type of <code>name</code> is
   1113          *         not serializable or if the field type is incorrect
   1114          */
   1115         public abstract boolean get(String name, boolean val)
   1116             throws IOException;
   1117 
   1118         /**
   1119          * Get the value of the named byte field from the persistent field.
   1120          *
   1121          * @param  name the name of the field
   1122          * @param  val the default value to use if <code>name</code> does not
   1123          *         have a value
   1124          * @return the value of the named <code>byte</code> field
   1125          * @throws IOException if there are I/O errors while reading from the
   1126          *         underlying <code>InputStream</code>
   1127          * @throws IllegalArgumentException if type of <code>name</code> is
   1128          *         not serializable or if the field type is incorrect
   1129          */
   1130         public abstract byte get(String name, byte val) throws IOException;
   1131 
   1132         /**
   1133          * Get the value of the named char field from the persistent field.
   1134          *
   1135          * @param  name the name of the field
   1136          * @param  val the default value to use if <code>name</code> does not
   1137          *         have a value
   1138          * @return the value of the named <code>char</code> field
   1139          * @throws IOException if there are I/O errors while reading from the
   1140          *         underlying <code>InputStream</code>
   1141          * @throws IllegalArgumentException if type of <code>name</code> is
   1142          *         not serializable or if the field type is incorrect
   1143          */
   1144         public abstract char get(String name, char val) throws IOException;
   1145 
   1146         /**
   1147          * Get the value of the named short field from the persistent field.
   1148          *
   1149          * @param  name the name of the field
   1150          * @param  val the default value to use if <code>name</code> does not
   1151          *         have a value
   1152          * @return the value of the named <code>short</code> field
   1153          * @throws IOException if there are I/O errors while reading from the
   1154          *         underlying <code>InputStream</code>
   1155          * @throws IllegalArgumentException if type of <code>name</code> is
   1156          *         not serializable or if the field type is incorrect
   1157          */
   1158         public abstract short get(String name, short val) throws IOException;
   1159 
   1160         /**
   1161          * Get the value of the named int field from the persistent field.
   1162          *
   1163          * @param  name the name of the field
   1164          * @param  val the default value to use if <code>name</code> does not
   1165          *         have a value
   1166          * @return the value of the named <code>int</code> field
   1167          * @throws IOException if there are I/O errors while reading from the
   1168          *         underlying <code>InputStream</code>
   1169          * @throws IllegalArgumentException if type of <code>name</code> is
   1170          *         not serializable or if the field type is incorrect
   1171          */
   1172         public abstract int get(String name, int val) throws IOException;
   1173 
   1174         /**
   1175          * Get the value of the named long field from the persistent field.
   1176          *
   1177          * @param  name the name of the field
   1178          * @param  val the default value to use if <code>name</code> does not
   1179          *         have a value
   1180          * @return the value of the named <code>long</code> field
   1181          * @throws IOException if there are I/O errors while reading from the
   1182          *         underlying <code>InputStream</code>
   1183          * @throws IllegalArgumentException if type of <code>name</code> is
   1184          *         not serializable or if the field type is incorrect
   1185          */
   1186         public abstract long get(String name, long val) throws IOException;
   1187 
   1188         /**
   1189          * Get the value of the named float field from the persistent field.
   1190          *
   1191          * @param  name the name of the field
   1192          * @param  val the default value to use if <code>name</code> does not
   1193          *         have a value
   1194          * @return the value of the named <code>float</code> field
   1195          * @throws IOException if there are I/O errors while reading from the
   1196          *         underlying <code>InputStream</code>
   1197          * @throws IllegalArgumentException if type of <code>name</code> is
   1198          *         not serializable or if the field type is incorrect
   1199          */
   1200         public abstract float get(String name, float val) throws IOException;
   1201 
   1202         /**
   1203          * Get the value of the named double field from the persistent field.
   1204          *
   1205          * @param  name the name of the field
   1206          * @param  val the default value to use if <code>name</code> does not
   1207          *         have a value
   1208          * @return the value of the named <code>double</code> field
   1209          * @throws IOException if there are I/O errors while reading from the
   1210          *         underlying <code>InputStream</code>
   1211          * @throws IllegalArgumentException if type of <code>name</code> is
   1212          *         not serializable or if the field type is incorrect
   1213          */
   1214         public abstract double get(String name, double val) throws IOException;
   1215 
   1216         /**
   1217          * Get the value of the named Object field from the persistent field.
   1218          *
   1219          * @param  name the name of the field
   1220          * @param  val the default value to use if <code>name</code> does not
   1221          *         have a value
   1222          * @return the value of the named <code>Object</code> field
   1223          * @throws IOException if there are I/O errors while reading from the
   1224          *         underlying <code>InputStream</code>
   1225          * @throws IllegalArgumentException if type of <code>name</code> is
   1226          *         not serializable or if the field type is incorrect
   1227          */
   1228         public abstract Object get(String name, Object val) throws IOException;
   1229     }
   1230 
   1231     /**
   1232      * Verifies that this (possibly subclass) instance can be constructed
   1233      * without violating security constraints: the subclass must not override
   1234      * security-sensitive non-final methods, or else the
   1235      * "enableSubclassImplementation" SerializablePermission is checked.
   1236      */
   1237     private void verifySubclass() {
   1238         Class<?> cl = getClass();
   1239         if (cl == ObjectInputStream.class) {
   1240             return;
   1241         }
   1242         SecurityManager sm = System.getSecurityManager();
   1243         if (sm == null) {
   1244             return;
   1245         }
   1246         processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
   1247         WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
   1248         Boolean result = Caches.subclassAudits.get(key);
   1249         if (result == null) {
   1250             result = Boolean.valueOf(auditSubclass(cl));
   1251             Caches.subclassAudits.putIfAbsent(key, result);
   1252         }
   1253         if (result.booleanValue()) {
   1254             return;
   1255         }
   1256         sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
   1257     }
   1258 
   1259     /**
   1260      * Performs reflective checks on given subclass to verify that it doesn't
   1261      * override security-sensitive non-final methods.  Returns true if subclass
   1262      * is "safe", false otherwise.
   1263      */
   1264     private static boolean auditSubclass(final Class<?> subcl) {
   1265         Boolean result = AccessController.doPrivileged(
   1266             new PrivilegedAction<Boolean>() {
   1267                 public Boolean run() {
   1268                     for (Class<?> cl = subcl;
   1269                          cl != ObjectInputStream.class;
   1270                          cl = cl.getSuperclass())
   1271                     {
   1272                         try {
   1273                             cl.getDeclaredMethod(
   1274                                 "readUnshared", (Class[]) null);
   1275                             return Boolean.FALSE;
   1276                         } catch (NoSuchMethodException ex) {
   1277                         }
   1278                         try {
   1279                             cl.getDeclaredMethod("readFields", (Class[]) null);
   1280                             return Boolean.FALSE;
   1281                         } catch (NoSuchMethodException ex) {
   1282                         }
   1283                     }
   1284                     return Boolean.TRUE;
   1285                 }
   1286             }
   1287         );
   1288         return result.booleanValue();
   1289     }
   1290 
   1291     /**
   1292      * Clears internal data structures.
   1293      */
   1294     private void clear() {
   1295         handles.clear();
   1296         vlist.clear();
   1297     }
   1298 
   1299     /**
   1300      * Underlying readObject implementation.
   1301      */
   1302     private Object readObject0(boolean unshared) throws IOException {
   1303         boolean oldMode = bin.getBlockDataMode();
   1304         if (oldMode) {
   1305             int remain = bin.currentBlockRemaining();
   1306             if (remain > 0) {
   1307                 throw new OptionalDataException(remain);
   1308             } else if (defaultDataEnd) {
   1309                 /*
   1310                  * Fix for 4360508: stream is currently at the end of a field
   1311                  * value block written via default serialization; since there
   1312                  * is no terminating TC_ENDBLOCKDATA tag, simulate
   1313                  * end-of-custom-data behavior explicitly.
   1314                  */
   1315                 throw new OptionalDataException(true);
   1316             }
   1317             bin.setBlockDataMode(false);
   1318         }
   1319 
   1320         byte tc;
   1321         while ((tc = bin.peekByte()) == TC_RESET) {
   1322             bin.readByte();
   1323             handleReset();
   1324         }
   1325 
   1326         depth++;
   1327         try {
   1328             switch (tc) {
   1329                 case TC_NULL:
   1330                     return readNull();
   1331 
   1332                 case TC_REFERENCE:
   1333                     return readHandle(unshared);
   1334 
   1335                 case TC_CLASS:
   1336                     return readClass(unshared);
   1337 
   1338                 case TC_CLASSDESC:
   1339                 case TC_PROXYCLASSDESC:
   1340                     return readClassDesc(unshared);
   1341 
   1342                 case TC_STRING:
   1343                 case TC_LONGSTRING:
   1344                     return checkResolve(readString(unshared));
   1345 
   1346                 case TC_ARRAY:
   1347                     return checkResolve(readArray(unshared));
   1348 
   1349                 case TC_ENUM:
   1350                     return checkResolve(readEnum(unshared));
   1351 
   1352                 case TC_OBJECT:
   1353                     return checkResolve(readOrdinaryObject(unshared));
   1354 
   1355                 case TC_EXCEPTION:
   1356                     IOException ex = readFatalException();
   1357                     throw new WriteAbortedException("writing aborted", ex);
   1358 
   1359                 case TC_BLOCKDATA:
   1360                 case TC_BLOCKDATALONG:
   1361                     if (oldMode) {
   1362                         bin.setBlockDataMode(true);
   1363                         bin.peek();             // force header read
   1364                         throw new OptionalDataException(
   1365                             bin.currentBlockRemaining());
   1366                     } else {
   1367                         throw new StreamCorruptedException(
   1368                             "unexpected block data");
   1369                     }
   1370 
   1371                 case TC_ENDBLOCKDATA:
   1372                     if (oldMode) {
   1373                         throw new OptionalDataException(true);
   1374                     } else {
   1375                         throw new StreamCorruptedException(
   1376                             "unexpected end of block data");
   1377                     }
   1378 
   1379                 default:
   1380                     throw new StreamCorruptedException(
   1381                         String.format("invalid type code: %02X", tc));
   1382             }
   1383         } finally {
   1384             depth--;
   1385             bin.setBlockDataMode(oldMode);
   1386         }
   1387     }
   1388 
   1389     /**
   1390      * If resolveObject has been enabled and given object does not have an
   1391      * exception associated with it, calls resolveObject to determine
   1392      * replacement for object, and updates handle table accordingly.  Returns
   1393      * replacement object, or echoes provided object if no replacement
   1394      * occurred.  Expects that passHandle is set to given object's handle prior
   1395      * to calling this method.
   1396      */
   1397     private Object checkResolve(Object obj) throws IOException {
   1398         if (!enableResolve || handles.lookupException(passHandle) != null) {
   1399             return obj;
   1400         }
   1401         Object rep = resolveObject(obj);
   1402         if (rep != obj) {
   1403             handles.setObject(passHandle, rep);
   1404         }
   1405         return rep;
   1406     }
   1407 
   1408     /**
   1409      * Reads string without allowing it to be replaced in stream.  Called from
   1410      * within ObjectStreamClass.read().
   1411      */
   1412     String readTypeString() throws IOException {
   1413         int oldHandle = passHandle;
   1414         try {
   1415             byte tc = bin.peekByte();
   1416             switch (tc) {
   1417                 case TC_NULL:
   1418                     return (String) readNull();
   1419 
   1420                 case TC_REFERENCE:
   1421                     return (String) readHandle(false);
   1422 
   1423                 case TC_STRING:
   1424                 case TC_LONGSTRING:
   1425                     return readString(false);
   1426 
   1427                 default:
   1428                     throw new StreamCorruptedException(
   1429                         String.format("invalid type code: %02X", tc));
   1430             }
   1431         } finally {
   1432             passHandle = oldHandle;
   1433         }
   1434     }
   1435 
   1436     /**
   1437      * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
   1438      */
   1439     private Object readNull() throws IOException {
   1440         if (bin.readByte() != TC_NULL) {
   1441             throw new InternalError();
   1442         }
   1443         passHandle = NULL_HANDLE;
   1444         return null;
   1445     }
   1446 
   1447     /**
   1448      * Reads in object handle, sets passHandle to the read handle, and returns
   1449      * object associated with the handle.
   1450      */
   1451     private Object readHandle(boolean unshared) throws IOException {
   1452         if (bin.readByte() != TC_REFERENCE) {
   1453             throw new InternalError();
   1454         }
   1455         passHandle = bin.readInt() - baseWireHandle;
   1456         if (passHandle < 0 || passHandle >= handles.size()) {
   1457             throw new StreamCorruptedException(
   1458                 String.format("invalid handle value: %08X", passHandle +
   1459                 baseWireHandle));
   1460         }
   1461         if (unshared) {
   1462             // REMIND: what type of exception to throw here?
   1463             throw new InvalidObjectException(
   1464                 "cannot read back reference as unshared");
   1465         }
   1466 
   1467         Object obj = handles.lookupObject(passHandle);
   1468         if (obj == unsharedMarker) {
   1469             // REMIND: what type of exception to throw here?
   1470             throw new InvalidObjectException(
   1471                 "cannot read back reference to unshared object");
   1472         }
   1473         return obj;
   1474     }
   1475 
   1476     /**
   1477      * Reads in and returns class object.  Sets passHandle to class object's
   1478      * assigned handle.  Returns null if class is unresolvable (in which case a
   1479      * ClassNotFoundException will be associated with the class' handle in the
   1480      * handle table).
   1481      */
   1482     private Class<?> readClass(boolean unshared) throws IOException {
   1483         if (bin.readByte() != TC_CLASS) {
   1484             throw new InternalError();
   1485         }
   1486         ObjectStreamClass desc = readClassDesc(false);
   1487         Class<?> cl = desc.forClass();
   1488         passHandle = handles.assign(unshared ? unsharedMarker : cl);
   1489 
   1490         ClassNotFoundException resolveEx = desc.getResolveException();
   1491         if (resolveEx != null) {
   1492             handles.markException(passHandle, resolveEx);
   1493         }
   1494 
   1495         handles.finish(passHandle);
   1496         return cl;
   1497     }
   1498 
   1499     /**
   1500      * Reads in and returns (possibly null) class descriptor.  Sets passHandle
   1501      * to class descriptor's assigned handle.  If class descriptor cannot be
   1502      * resolved to a class in the local VM, a ClassNotFoundException is
   1503      * associated with the class descriptor's handle.
   1504      */
   1505     private ObjectStreamClass readClassDesc(boolean unshared)
   1506         throws IOException
   1507     {
   1508         byte tc = bin.peekByte();
   1509         switch (tc) {
   1510             case TC_NULL:
   1511                 return (ObjectStreamClass) readNull();
   1512 
   1513             case TC_REFERENCE:
   1514                 return (ObjectStreamClass) readHandle(unshared);
   1515 
   1516             case TC_PROXYCLASSDESC:
   1517                 return readProxyDesc(unshared);
   1518 
   1519             case TC_CLASSDESC:
   1520                 return readNonProxyDesc(unshared);
   1521 
   1522             default:
   1523                 throw new StreamCorruptedException(
   1524                     String.format("invalid type code: %02X", tc));
   1525         }
   1526     }
   1527 
   1528     private boolean isCustomSubclass() {
   1529         // Return true if this class is a custom subclass of ObjectInputStream
   1530         return getClass().getClassLoader()
   1531                     != ObjectInputStream.class.getClassLoader();
   1532     }
   1533 
   1534     /**
   1535      * Reads in and returns class descriptor for a dynamic proxy class.  Sets
   1536      * passHandle to proxy class descriptor's assigned handle.  If proxy class
   1537      * descriptor cannot be resolved to a class in the local VM, a
   1538      * ClassNotFoundException is associated with the descriptor's handle.
   1539      */
   1540     private ObjectStreamClass readProxyDesc(boolean unshared)
   1541         throws IOException
   1542     {
   1543         if (bin.readByte() != TC_PROXYCLASSDESC) {
   1544             throw new InternalError();
   1545         }
   1546 
   1547         ObjectStreamClass desc = new ObjectStreamClass();
   1548         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
   1549         passHandle = NULL_HANDLE;
   1550 
   1551         int numIfaces = bin.readInt();
   1552         String[] ifaces = new String[numIfaces];
   1553         for (int i = 0; i < numIfaces; i++) {
   1554             ifaces[i] = bin.readUTF();
   1555         }
   1556 
   1557         Class<?> cl = null;
   1558         ClassNotFoundException resolveEx = null;
   1559         bin.setBlockDataMode(true);
   1560         try {
   1561             if ((cl = resolveProxyClass(ifaces)) == null) {
   1562                 resolveEx = new ClassNotFoundException("null class");
   1563             } else if (!Proxy.isProxyClass(cl)) {
   1564                 throw new InvalidClassException("Not a proxy");
   1565             } else {
   1566                 // ReflectUtil.checkProxyPackageAccess makes a test
   1567                 // equivalent to isCustomSubclass so there's no need
   1568                 // to condition this call to isCustomSubclass == true here.
   1569                 ReflectUtil.checkProxyPackageAccess(
   1570                         getClass().getClassLoader(),
   1571                         cl.getInterfaces());
   1572             }
   1573         } catch (ClassNotFoundException ex) {
   1574             resolveEx = ex;
   1575         }
   1576         skipCustomData();
   1577 
   1578         desc.initProxy(cl, resolveEx, readClassDesc(false));
   1579 
   1580         handles.finish(descHandle);
   1581         passHandle = descHandle;
   1582         return desc;
   1583     }
   1584 
   1585     /**
   1586      * Reads in and returns class descriptor for a class that is not a dynamic
   1587      * proxy class.  Sets passHandle to class descriptor's assigned handle.  If
   1588      * class descriptor cannot be resolved to a class in the local VM, a
   1589      * ClassNotFoundException is associated with the descriptor's handle.
   1590      */
   1591     private ObjectStreamClass readNonProxyDesc(boolean unshared)
   1592         throws IOException
   1593     {
   1594         if (bin.readByte() != TC_CLASSDESC) {
   1595             throw new InternalError();
   1596         }
   1597 
   1598         ObjectStreamClass desc = new ObjectStreamClass();
   1599         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
   1600         passHandle = NULL_HANDLE;
   1601 
   1602         ObjectStreamClass readDesc = null;
   1603         try {
   1604             readDesc = readClassDescriptor();
   1605         } catch (ClassNotFoundException ex) {
   1606             throw (IOException) new InvalidClassException(
   1607                 "failed to read class descriptor").initCause(ex);
   1608         }
   1609 
   1610         Class<?> cl = null;
   1611         ClassNotFoundException resolveEx = null;
   1612         bin.setBlockDataMode(true);
   1613         final boolean checksRequired = isCustomSubclass();
   1614         try {
   1615             if ((cl = resolveClass(readDesc)) == null) {
   1616                 resolveEx = new ClassNotFoundException("null class");
   1617             } else if (checksRequired) {
   1618                 ReflectUtil.checkPackageAccess(cl);
   1619             }
   1620         } catch (ClassNotFoundException ex) {
   1621             resolveEx = ex;
   1622         }
   1623         skipCustomData();
   1624 
   1625         desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
   1626 
   1627         handles.finish(descHandle);
   1628         passHandle = descHandle;
   1629         return desc;
   1630     }
   1631 
   1632     /**
   1633      * Reads in and returns new string.  Sets passHandle to new string's
   1634      * assigned handle.
   1635      */
   1636     private String readString(boolean unshared) throws IOException {
   1637         String str;
   1638         byte tc = bin.readByte();
   1639         switch (tc) {
   1640             case TC_STRING:
   1641                 str = bin.readUTF();
   1642                 break;
   1643 
   1644             case TC_LONGSTRING:
   1645                 str = bin.readLongUTF();
   1646                 break;
   1647 
   1648             default:
   1649                 throw new StreamCorruptedException(
   1650                     String.format("invalid type code: %02X", tc));
   1651         }
   1652         passHandle = handles.assign(unshared ? unsharedMarker : str);
   1653         handles.finish(passHandle);
   1654         return str;
   1655     }
   1656 
   1657     /**
   1658      * Reads in and returns array object, or null if array class is
   1659      * unresolvable.  Sets passHandle to array's assigned handle.
   1660      */
   1661     private Object readArray(boolean unshared) throws IOException {
   1662         if (bin.readByte() != TC_ARRAY) {
   1663             throw new InternalError();
   1664         }
   1665 
   1666         ObjectStreamClass desc = readClassDesc(false);
   1667         int len = bin.readInt();
   1668 
   1669         Object array = null;
   1670         Class<?> cl, ccl = null;
   1671         if ((cl = desc.forClass()) != null) {
   1672             ccl = cl.getComponentType();
   1673             array = Array.newInstance(ccl, len);
   1674         }
   1675 
   1676         int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
   1677         ClassNotFoundException resolveEx = desc.getResolveException();
   1678         if (resolveEx != null) {
   1679             handles.markException(arrayHandle, resolveEx);
   1680         }
   1681 
   1682         if (ccl == null) {
   1683             for (int i = 0; i < len; i++) {
   1684                 readObject0(false);
   1685             }
   1686         } else if (ccl.isPrimitive()) {
   1687             if (ccl == Integer.TYPE) {
   1688                 bin.readInts((int[]) array, 0, len);
   1689             } else if (ccl == Byte.TYPE) {
   1690                 bin.readFully((byte[]) array, 0, len, true);
   1691             } else if (ccl == Long.TYPE) {
   1692                 bin.readLongs((long[]) array, 0, len);
   1693             } else if (ccl == Float.TYPE) {
   1694                 bin.readFloats((float[]) array, 0, len);
   1695             } else if (ccl == Double.TYPE) {
   1696                 bin.readDoubles((double[]) array, 0, len);
   1697             } else if (ccl == Short.TYPE) {
   1698                 bin.readShorts((short[]) array, 0, len);
   1699             } else if (ccl == Character.TYPE) {
   1700                 bin.readChars((char[]) array, 0, len);
   1701             } else if (ccl == Boolean.TYPE) {
   1702                 bin.readBooleans((boolean[]) array, 0, len);
   1703             } else {
   1704                 throw new InternalError();
   1705             }
   1706         } else {
   1707             Object[] oa = (Object[]) array;
   1708             for (int i = 0; i < len; i++) {
   1709                 oa[i] = readObject0(false);
   1710                 handles.markDependency(arrayHandle, passHandle);
   1711             }
   1712         }
   1713 
   1714         handles.finish(arrayHandle);
   1715         passHandle = arrayHandle;
   1716         return array;
   1717     }
   1718 
   1719     /**
   1720      * Reads in and returns enum constant, or null if enum type is
   1721      * unresolvable.  Sets passHandle to enum constant's assigned handle.
   1722      */
   1723     private Enum<?> readEnum(boolean unshared) throws IOException {
   1724         if (bin.readByte() != TC_ENUM) {
   1725             throw new InternalError();
   1726         }
   1727 
   1728         ObjectStreamClass desc = readClassDesc(false);
   1729         if (!desc.isEnum()) {
   1730             throw new InvalidClassException("non-enum class: " + desc);
   1731         }
   1732 
   1733         int enumHandle = handles.assign(unshared ? unsharedMarker : null);
   1734         ClassNotFoundException resolveEx = desc.getResolveException();
   1735         if (resolveEx != null) {
   1736             handles.markException(enumHandle, resolveEx);
   1737         }
   1738 
   1739         String name = readString(false);
   1740         Enum<?> result = null;
   1741         Class<?> cl = desc.forClass();
   1742         if (cl != null) {
   1743             try {
   1744                 @SuppressWarnings("unchecked")
   1745                 Enum<?> en = Enum.valueOf((Class)cl, name);
   1746                 result = en;
   1747             } catch (IllegalArgumentException ex) {
   1748                 throw (IOException) new InvalidObjectException(
   1749                     "enum constant " + name + " does not exist in " +
   1750                     cl).initCause(ex);
   1751             }
   1752             if (!unshared) {
   1753                 handles.setObject(enumHandle, result);
   1754             }
   1755         }
   1756 
   1757         handles.finish(enumHandle);
   1758         passHandle = enumHandle;
   1759         return result;
   1760     }
   1761 
   1762     /**
   1763      * Reads and returns "ordinary" (i.e., not a String, Class,
   1764      * ObjectStreamClass, array, or enum constant) object, or null if object's
   1765      * class is unresolvable (in which case a ClassNotFoundException will be
   1766      * associated with object's handle).  Sets passHandle to object's assigned
   1767      * handle.
   1768      */
   1769     private Object readOrdinaryObject(boolean unshared)
   1770         throws IOException
   1771     {
   1772         if (bin.readByte() != TC_OBJECT) {
   1773             throw new InternalError();
   1774         }
   1775 
   1776         ObjectStreamClass desc = readClassDesc(false);
   1777         desc.checkDeserialize();
   1778 
   1779         Class<?> cl = desc.forClass();
   1780         if (cl == String.class || cl == Class.class
   1781                 || cl == ObjectStreamClass.class) {
   1782             throw new InvalidClassException("invalid class descriptor");
   1783         }
   1784 
   1785         Object obj;
   1786         try {
   1787             obj = desc.isInstantiable() ? desc.newInstance() : null;
   1788         } catch (Exception ex) {
   1789             throw (IOException) new InvalidClassException(
   1790                 desc.forClass().getName(),
   1791                 "unable to create instance").initCause(ex);
   1792         }
   1793 
   1794         passHandle = handles.assign(unshared ? unsharedMarker : obj);
   1795         ClassNotFoundException resolveEx = desc.getResolveException();
   1796         if (resolveEx != null) {
   1797             handles.markException(passHandle, resolveEx);
   1798         }
   1799 
   1800         if (desc.isExternalizable()) {
   1801             readExternalData((Externalizable) obj, desc);
   1802         } else {
   1803             readSerialData(obj, desc);
   1804         }
   1805 
   1806         handles.finish(passHandle);
   1807 
   1808         if (obj != null &&
   1809             handles.lookupException(passHandle) == null &&
   1810             desc.hasReadResolveMethod())
   1811         {
   1812             Object rep = desc.invokeReadResolve(obj);
   1813             if (unshared && rep.getClass().isArray()) {
   1814                 rep = cloneArray(rep);
   1815             }
   1816             if (rep != obj) {
   1817                 handles.setObject(passHandle, obj = rep);
   1818             }
   1819         }
   1820 
   1821         return obj;
   1822     }
   1823 
   1824     /**
   1825      * If obj is non-null, reads externalizable data by invoking readExternal()
   1826      * method of obj; otherwise, attempts to skip over externalizable data.
   1827      * Expects that passHandle is set to obj's handle before this method is
   1828      * called.
   1829      */
   1830     private void readExternalData(Externalizable obj, ObjectStreamClass desc)
   1831         throws IOException
   1832     {
   1833         SerialCallbackContext oldContext = curContext;
   1834         if (oldContext != null)
   1835             oldContext.check();
   1836         curContext = null;
   1837         try {
   1838             boolean blocked = desc.hasBlockExternalData();
   1839             if (blocked) {
   1840                 bin.setBlockDataMode(true);
   1841             }
   1842             if (obj != null) {
   1843                 try {
   1844                     obj.readExternal(this);
   1845                 } catch (ClassNotFoundException ex) {
   1846                     /*
   1847                      * In most cases, the handle table has already propagated
   1848                      * a CNFException to passHandle at this point; this mark
   1849                      * call is included to address cases where the readExternal
   1850                      * method has cons'ed and thrown a new CNFException of its
   1851                      * own.
   1852                      */
   1853                      handles.markException(passHandle, ex);
   1854                 }
   1855             }
   1856             if (blocked) {
   1857                 skipCustomData();
   1858             }
   1859         } finally {
   1860             if (oldContext != null)
   1861                 oldContext.check();
   1862             curContext = oldContext;
   1863         }
   1864         /*
   1865          * At this point, if the externalizable data was not written in
   1866          * block-data form and either the externalizable class doesn't exist
   1867          * locally (i.e., obj == null) or readExternal() just threw a
   1868          * CNFException, then the stream is probably in an inconsistent state,
   1869          * since some (or all) of the externalizable data may not have been
   1870          * consumed.  Since there's no "correct" action to take in this case,
   1871          * we mimic the behavior of past serialization implementations and
   1872          * blindly hope that the stream is in sync; if it isn't and additional
   1873          * externalizable data remains in the stream, a subsequent read will
   1874          * most likely throw a StreamCorruptedException.
   1875          */
   1876     }
   1877 
   1878     /**
   1879      * Reads (or attempts to skip, if obj is null or is tagged with a
   1880      * ClassNotFoundException) instance data for each serializable class of
   1881      * object in stream, from superclass to subclass.  Expects that passHandle
   1882      * is set to obj's handle before this method is called.
   1883      */
   1884     private void readSerialData(Object obj, ObjectStreamClass desc)
   1885         throws IOException
   1886     {
   1887         ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
   1888         for (int i = 0; i < slots.length; i++) {
   1889             ObjectStreamClass slotDesc = slots[i].desc;
   1890 
   1891             if (slots[i].hasData) {
   1892                 if (obj == null || handles.lookupException(passHandle) != null) {
   1893                     defaultReadFields(null, slotDesc); // skip field values
   1894                 } else if (slotDesc.hasReadObjectMethod()) {
   1895                     SerialCallbackContext oldContext = curContext;
   1896                     if (oldContext != null)
   1897                         oldContext.check();
   1898                     try {
   1899                         curContext = new SerialCallbackContext(obj, slotDesc);
   1900 
   1901                         bin.setBlockDataMode(true);
   1902                         slotDesc.invokeReadObject(obj, this);
   1903                     } catch (ClassNotFoundException ex) {
   1904                         /*
   1905                          * In most cases, the handle table has already
   1906                          * propagated a CNFException to passHandle at this
   1907                          * point; this mark call is included to address cases
   1908                          * where the custom readObject method has cons'ed and
   1909                          * thrown a new CNFException of its own.
   1910                          */
   1911                         handles.markException(passHandle, ex);
   1912                     } finally {
   1913                         curContext.setUsed();
   1914                         if (oldContext!= null)
   1915                             oldContext.check();
   1916                         curContext = oldContext;
   1917                     }
   1918 
   1919                     /*
   1920                      * defaultDataEnd may have been set indirectly by custom
   1921                      * readObject() method when calling defaultReadObject() or
   1922                      * readFields(); clear it to restore normal read behavior.
   1923                      */
   1924                     defaultDataEnd = false;
   1925                 } else {
   1926                     defaultReadFields(obj, slotDesc);
   1927                 }
   1928 
   1929                 if (slotDesc.hasWriteObjectData()) {
   1930                     skipCustomData();
   1931                 } else {
   1932                     bin.setBlockDataMode(false);
   1933                 }
   1934             } else {
   1935                 if (obj != null &&
   1936                     slotDesc.hasReadObjectNoDataMethod() &&
   1937                     handles.lookupException(passHandle) == null)
   1938                 {
   1939                     slotDesc.invokeReadObjectNoData(obj);
   1940                 }
   1941             }
   1942         }
   1943     }
   1944 
   1945     /**
   1946      * Skips over all block data and objects until TC_ENDBLOCKDATA is
   1947      * encountered.
   1948      */
   1949     private void skipCustomData() throws IOException {
   1950         int oldHandle = passHandle;
   1951         for (;;) {
   1952             if (bin.getBlockDataMode()) {
   1953                 bin.skipBlockData();
   1954                 bin.setBlockDataMode(false);
   1955             }
   1956             switch (bin.peekByte()) {
   1957                 case TC_BLOCKDATA:
   1958                 case TC_BLOCKDATALONG:
   1959                     bin.setBlockDataMode(true);
   1960                     break;
   1961 
   1962                 case TC_ENDBLOCKDATA:
   1963                     bin.readByte();
   1964                     passHandle = oldHandle;
   1965                     return;
   1966 
   1967                 default:
   1968                     readObject0(false);
   1969                     break;
   1970             }
   1971         }
   1972     }
   1973 
   1974     /**
   1975      * Reads in values of serializable fields declared by given class
   1976      * descriptor.  If obj is non-null, sets field values in obj.  Expects that
   1977      * passHandle is set to obj's handle before this method is called.
   1978      */
   1979     private void defaultReadFields(Object obj, ObjectStreamClass desc)
   1980         throws IOException
   1981     {
   1982         Class<?> cl = desc.forClass();
   1983         if (cl != null && obj != null && !cl.isInstance(obj)) {
   1984             throw new ClassCastException();
   1985         }
   1986 
   1987         int primDataSize = desc.getPrimDataSize();
   1988         if (primVals == null || primVals.length < primDataSize) {
   1989             primVals = new byte[primDataSize];
   1990         }
   1991         bin.readFully(primVals, 0, primDataSize, false);
   1992         if (obj != null) {
   1993             desc.setPrimFieldValues(obj, primVals);
   1994         }
   1995 
   1996         int objHandle = passHandle;
   1997         ObjectStreamField[] fields = desc.getFields(false);
   1998         Object[] objVals = new Object[desc.getNumObjFields()];
   1999         int numPrimFields = fields.length - objVals.length;
   2000         for (int i = 0; i < objVals.length; i++) {
   2001             ObjectStreamField f = fields[numPrimFields + i];
   2002             objVals[i] = readObject0(f.isUnshared());
   2003             if (f.getField() != null) {
   2004                 handles.markDependency(objHandle, passHandle);
   2005             }
   2006         }
   2007         if (obj != null) {
   2008             desc.setObjFieldValues(obj, objVals);
   2009         }
   2010         passHandle = objHandle;
   2011     }
   2012 
   2013     /**
   2014      * Reads in and returns IOException that caused serialization to abort.
   2015      * All stream state is discarded prior to reading in fatal exception.  Sets
   2016      * passHandle to fatal exception's handle.
   2017      */
   2018     private IOException readFatalException() throws IOException {
   2019         if (bin.readByte() != TC_EXCEPTION) {
   2020             throw new InternalError();
   2021         }
   2022         clear();
   2023         // BEGIN Android-changed: Fix SerializationStressTest#test_2_writeReplace.
   2024         IOException e = (IOException) readObject0(false);
   2025         // If we want to continue reading from same stream after fatal exception, we
   2026         // need to clear internal data structures.
   2027         clear();
   2028         return e;
   2029         // END Android-changed: Fix SerializationStressTest#test_2_writeReplace.
   2030     }
   2031 
   2032     /**
   2033      * If recursion depth is 0, clears internal data structures; otherwise,
   2034      * throws a StreamCorruptedException.  This method is called when a
   2035      * TC_RESET typecode is encountered.
   2036      */
   2037     private void handleReset() throws StreamCorruptedException {
   2038         if (depth > 0) {
   2039             throw new StreamCorruptedException(
   2040                 "unexpected reset; recursion depth: " + depth);
   2041         }
   2042         clear();
   2043     }
   2044 
   2045     /**
   2046      * Converts specified span of bytes into float values.
   2047      */
   2048     // REMIND: remove once hotspot inlines Float.intBitsToFloat
   2049     private static native void bytesToFloats(byte[] src, int srcpos,
   2050                                              float[] dst, int dstpos,
   2051                                              int nfloats);
   2052 
   2053     /**
   2054      * Converts specified span of bytes into double values.
   2055      */
   2056     // REMIND: remove once hotspot inlines Double.longBitsToDouble
   2057     private static native void bytesToDoubles(byte[] src, int srcpos,
   2058                                               double[] dst, int dstpos,
   2059                                               int ndoubles);
   2060 
   2061     /**
   2062      * Returns the first non-null class loader (not counting class loaders of
   2063      * generated reflection implementation classes) up the execution stack, or
   2064      * null if only code from the null class loader is on the stack.  This
   2065      * method is also called via reflection by the following RMI-IIOP class:
   2066      *
   2067      *     com.sun.corba.se.internal.util.JDKClassLoader
   2068      *
   2069      * This method should not be removed or its signature changed without
   2070      * corresponding modifications to the above class.
   2071      */
   2072     private static ClassLoader latestUserDefinedLoader() {
   2073         // Android-changed: Use VMStack on Android.
   2074         return VMStack.getClosestUserClassLoader();
   2075     }
   2076 
   2077     /**
   2078      * Default GetField implementation.
   2079      */
   2080     private class GetFieldImpl extends GetField {
   2081 
   2082         /** class descriptor describing serializable fields */
   2083         private final ObjectStreamClass desc;
   2084         /** primitive field values */
   2085         private final byte[] primVals;
   2086         /** object field values */
   2087         private final Object[] objVals;
   2088         /** object field value handles */
   2089         private final int[] objHandles;
   2090 
   2091         /**
   2092          * Creates GetFieldImpl object for reading fields defined in given
   2093          * class descriptor.
   2094          */
   2095         GetFieldImpl(ObjectStreamClass desc) {
   2096             this.desc = desc;
   2097             primVals = new byte[desc.getPrimDataSize()];
   2098             objVals = new Object[desc.getNumObjFields()];
   2099             objHandles = new int[objVals.length];
   2100         }
   2101 
   2102         public ObjectStreamClass getObjectStreamClass() {
   2103             return desc;
   2104         }
   2105 
   2106         public boolean defaulted(String name) throws IOException {
   2107             return (getFieldOffset(name, null) < 0);
   2108         }
   2109 
   2110         public boolean get(String name, boolean val) throws IOException {
   2111             int off = getFieldOffset(name, Boolean.TYPE);
   2112             return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
   2113         }
   2114 
   2115         public byte get(String name, byte val) throws IOException {
   2116             int off = getFieldOffset(name, Byte.TYPE);
   2117             return (off >= 0) ? primVals[off] : val;
   2118         }
   2119 
   2120         public char get(String name, char val) throws IOException {
   2121             int off = getFieldOffset(name, Character.TYPE);
   2122             return (off >= 0) ? Bits.getChar(primVals, off) : val;
   2123         }
   2124 
   2125         public short get(String name, short val) throws IOException {
   2126             int off = getFieldOffset(name, Short.TYPE);
   2127             return (off >= 0) ? Bits.getShort(primVals, off) : val;
   2128         }
   2129 
   2130         public int get(String name, int val) throws IOException {
   2131             int off = getFieldOffset(name, Integer.TYPE);
   2132             return (off >= 0) ? Bits.getInt(primVals, off) : val;
   2133         }
   2134 
   2135         public float get(String name, float val) throws IOException {
   2136             int off = getFieldOffset(name, Float.TYPE);
   2137             return (off >= 0) ? Bits.getFloat(primVals, off) : val;
   2138         }
   2139 
   2140         public long get(String name, long val) throws IOException {
   2141             int off = getFieldOffset(name, Long.TYPE);
   2142             return (off >= 0) ? Bits.getLong(primVals, off) : val;
   2143         }
   2144 
   2145         public double get(String name, double val) throws IOException {
   2146             int off = getFieldOffset(name, Double.TYPE);
   2147             return (off >= 0) ? Bits.getDouble(primVals, off) : val;
   2148         }
   2149 
   2150         public Object get(String name, Object val) throws IOException {
   2151             int off = getFieldOffset(name, Object.class);
   2152             if (off >= 0) {
   2153                 int objHandle = objHandles[off];
   2154                 handles.markDependency(passHandle, objHandle);
   2155                 return (handles.lookupException(objHandle) == null) ?
   2156                     objVals[off] : null;
   2157             } else {
   2158                 return val;
   2159             }
   2160         }
   2161 
   2162         /**
   2163          * Reads primitive and object field values from stream.
   2164          */
   2165         void readFields() throws IOException {
   2166             bin.readFully(primVals, 0, primVals.length, false);
   2167 
   2168             int oldHandle = passHandle;
   2169             ObjectStreamField[] fields = desc.getFields(false);
   2170             int numPrimFields = fields.length - objVals.length;
   2171             for (int i = 0; i < objVals.length; i++) {
   2172                 objVals[i] =
   2173                     readObject0(fields[numPrimFields + i].isUnshared());
   2174                 objHandles[i] = passHandle;
   2175             }
   2176             passHandle = oldHandle;
   2177         }
   2178 
   2179         /**
   2180          * Returns offset of field with given name and type.  A specified type
   2181          * of null matches all types, Object.class matches all non-primitive
   2182          * types, and any other non-null type matches assignable types only.
   2183          * If no matching field is found in the (incoming) class
   2184          * descriptor but a matching field is present in the associated local
   2185          * class descriptor, returns -1.  Throws IllegalArgumentException if
   2186          * neither incoming nor local class descriptor contains a match.
   2187          */
   2188         private int getFieldOffset(String name, Class<?> type) {
   2189             ObjectStreamField field = desc.getField(name, type);
   2190             if (field != null) {
   2191                 return field.getOffset();
   2192             } else if (desc.getLocalDesc().getField(name, type) != null) {
   2193                 return -1;
   2194             } else {
   2195                 throw new IllegalArgumentException("no such field " + name +
   2196                                                    " with type " + type);
   2197             }
   2198         }
   2199     }
   2200 
   2201     /**
   2202      * Prioritized list of callbacks to be performed once object graph has been
   2203      * completely deserialized.
   2204      */
   2205     private static class ValidationList {
   2206 
   2207         private static class Callback {
   2208             final ObjectInputValidation obj;
   2209             final int priority;
   2210             Callback next;
   2211             final AccessControlContext acc;
   2212 
   2213             Callback(ObjectInputValidation obj, int priority, Callback next,
   2214                 AccessControlContext acc)
   2215             {
   2216                 this.obj = obj;
   2217                 this.priority = priority;
   2218                 this.next = next;
   2219                 this.acc = acc;
   2220             }
   2221         }
   2222 
   2223         /** linked list of callbacks */
   2224         private Callback list;
   2225 
   2226         /**
   2227          * Creates new (empty) ValidationList.
   2228          */
   2229         ValidationList() {
   2230         }
   2231 
   2232         /**
   2233          * Registers callback.  Throws InvalidObjectException if callback
   2234          * object is null.
   2235          */
   2236         void register(ObjectInputValidation obj, int priority)
   2237             throws InvalidObjectException
   2238         {
   2239             if (obj == null) {
   2240                 throw new InvalidObjectException("null callback");
   2241             }
   2242 
   2243             Callback prev = null, cur = list;
   2244             while (cur != null && priority < cur.priority) {
   2245                 prev = cur;
   2246                 cur = cur.next;
   2247             }
   2248             AccessControlContext acc = AccessController.getContext();
   2249             if (prev != null) {
   2250                 prev.next = new Callback(obj, priority, cur, acc);
   2251             } else {
   2252                 list = new Callback(obj, priority, list, acc);
   2253             }
   2254         }
   2255 
   2256         /**
   2257          * Invokes all registered callbacks and clears the callback list.
   2258          * Callbacks with higher priorities are called first; those with equal
   2259          * priorities may be called in any order.  If any of the callbacks
   2260          * throws an InvalidObjectException, the callback process is terminated
   2261          * and the exception propagated upwards.
   2262          */
   2263         void doCallbacks() throws InvalidObjectException {
   2264             try {
   2265                 while (list != null) {
   2266                     AccessController.doPrivileged(
   2267                         new PrivilegedExceptionAction<Void>()
   2268                     {
   2269                         public Void run() throws InvalidObjectException {
   2270                             list.obj.validateObject();
   2271                             return null;
   2272                         }
   2273                     }, list.acc);
   2274                     list = list.next;
   2275                 }
   2276             } catch (PrivilegedActionException ex) {
   2277                 list = null;
   2278                 throw (InvalidObjectException) ex.getException();
   2279             }
   2280         }
   2281 
   2282         /**
   2283          * Resets the callback list to its initial (empty) state.
   2284          */
   2285         public void clear() {
   2286             list = null;
   2287         }
   2288     }
   2289 
   2290     /**
   2291      * Input stream supporting single-byte peek operations.
   2292      */
   2293     private static class PeekInputStream extends InputStream {
   2294 
   2295         /** underlying stream */
   2296         private final InputStream in;
   2297         /** peeked byte */
   2298         private int peekb = -1;
   2299 
   2300         /**
   2301          * Creates new PeekInputStream on top of given underlying stream.
   2302          */
   2303         PeekInputStream(InputStream in) {
   2304             this.in = in;
   2305         }
   2306 
   2307         /**
   2308          * Peeks at next byte value in stream.  Similar to read(), except
   2309          * that it does not consume the read value.
   2310          */
   2311         int peek() throws IOException {
   2312             return (peekb >= 0) ? peekb : (peekb = in.read());
   2313         }
   2314 
   2315         public int read() throws IOException {
   2316             if (peekb >= 0) {
   2317                 int v = peekb;
   2318                 peekb = -1;
   2319                 return v;
   2320             } else {
   2321                 return in.read();
   2322             }
   2323         }
   2324 
   2325         public int read(byte[] b, int off, int len) throws IOException {
   2326             if (len == 0) {
   2327                 return 0;
   2328             } else if (peekb < 0) {
   2329                 return in.read(b, off, len);
   2330             } else {
   2331                 b[off++] = (byte) peekb;
   2332                 len--;
   2333                 peekb = -1;
   2334                 int n = in.read(b, off, len);
   2335                 return (n >= 0) ? (n + 1) : 1;
   2336             }
   2337         }
   2338 
   2339         void readFully(byte[] b, int off, int len) throws IOException {
   2340             int n = 0;
   2341             while (n < len) {
   2342                 int count = read(b, off + n, len - n);
   2343                 if (count < 0) {
   2344                     throw new EOFException();
   2345                 }
   2346                 n += count;
   2347             }
   2348         }
   2349 
   2350         public long skip(long n) throws IOException {
   2351             if (n <= 0) {
   2352                 return 0;
   2353             }
   2354             int skipped = 0;
   2355             if (peekb >= 0) {
   2356                 peekb = -1;
   2357                 skipped++;
   2358                 n--;
   2359             }
   2360             return skipped + skip(n);
   2361         }
   2362 
   2363         public int available() throws IOException {
   2364             return in.available() + ((peekb >= 0) ? 1 : 0);
   2365         }
   2366 
   2367         public void close() throws IOException {
   2368             in.close();
   2369         }
   2370     }
   2371 
   2372     /**
   2373      * Input stream with two modes: in default mode, inputs data written in the
   2374      * same format as DataOutputStream; in "block data" mode, inputs data
   2375      * bracketed by block data markers (see object serialization specification
   2376      * for details).  Buffering depends on block data mode: when in default
   2377      * mode, no data is buffered in advance; when in block data mode, all data
   2378      * for the current data block is read in at once (and buffered).
   2379      */
   2380     private class BlockDataInputStream
   2381         extends InputStream implements DataInput
   2382     {
   2383         /** maximum data block length */
   2384         private static final int MAX_BLOCK_SIZE = 1024;
   2385         /** maximum data block header length */
   2386         private static final int MAX_HEADER_SIZE = 5;
   2387         /** (tunable) length of char buffer (for reading strings) */
   2388         private static final int CHAR_BUF_SIZE = 256;
   2389         /** readBlockHeader() return value indicating header read may block */
   2390         private static final int HEADER_BLOCKED = -2;
   2391 
   2392         /** buffer for reading general/block data */
   2393         private final byte[] buf = new byte[MAX_BLOCK_SIZE];
   2394         /** buffer for reading block data headers */
   2395         private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
   2396         /** char buffer for fast string reads */
   2397         private final char[] cbuf = new char[CHAR_BUF_SIZE];
   2398 
   2399         /** block data mode */
   2400         private boolean blkmode = false;
   2401 
   2402         // block data state fields; values meaningful only when blkmode true
   2403         /** current offset into buf */
   2404         private int pos = 0;
   2405         /** end offset of valid data in buf, or -1 if no more block data */
   2406         private int end = -1;
   2407         /** number of bytes in current block yet to be read from stream */
   2408         private int unread = 0;
   2409 
   2410         /** underlying stream (wrapped in peekable filter stream) */
   2411         private final PeekInputStream in;
   2412         /** loopback stream (for data reads that span data blocks) */
   2413         private final DataInputStream din;
   2414 
   2415         /**
   2416          * Creates new BlockDataInputStream on top of given underlying stream.
   2417          * Block data mode is turned off by default.
   2418          */
   2419         BlockDataInputStream(InputStream in) {
   2420             this.in = new PeekInputStream(in);
   2421             din = new DataInputStream(this);
   2422         }
   2423 
   2424         /**
   2425          * Sets block data mode to the given mode (true == on, false == off)
   2426          * and returns the previous mode value.  If the new mode is the same as
   2427          * the old mode, no action is taken.  Throws IllegalStateException if
   2428          * block data mode is being switched from on to off while unconsumed
   2429          * block data is still present in the stream.
   2430          */
   2431         boolean setBlockDataMode(boolean newmode) throws IOException {
   2432             if (blkmode == newmode) {
   2433                 return blkmode;
   2434             }
   2435             if (newmode) {
   2436                 pos = 0;
   2437                 end = 0;
   2438                 unread = 0;
   2439             } else if (pos < end) {
   2440                 throw new IllegalStateException("unread block data");
   2441             }
   2442             blkmode = newmode;
   2443             return !blkmode;
   2444         }
   2445 
   2446         /**
   2447          * Returns true if the stream is currently in block data mode, false
   2448          * otherwise.
   2449          */
   2450         boolean getBlockDataMode() {
   2451             return blkmode;
   2452         }
   2453 
   2454         /**
   2455          * If in block data mode, skips to the end of the current group of data
   2456          * blocks (but does not unset block data mode).  If not in block data
   2457          * mode, throws an IllegalStateException.
   2458          */
   2459         void skipBlockData() throws IOException {
   2460             if (!blkmode) {
   2461                 throw new IllegalStateException("not in block data mode");
   2462             }
   2463             while (end >= 0) {
   2464                 refill();
   2465             }
   2466         }
   2467 
   2468         /**
   2469          * Attempts to read in the next block data header (if any).  If
   2470          * canBlock is false and a full header cannot be read without possibly
   2471          * blocking, returns HEADER_BLOCKED, else if the next element in the
   2472          * stream is a block data header, returns the block data length
   2473          * specified by the header, else returns -1.
   2474          */
   2475         private int readBlockHeader(boolean canBlock) throws IOException {
   2476             if (defaultDataEnd) {
   2477                 /*
   2478                  * Fix for 4360508: stream is currently at the end of a field
   2479                  * value block written via default serialization; since there
   2480                  * is no terminating TC_ENDBLOCKDATA tag, simulate
   2481                  * end-of-custom-data behavior explicitly.
   2482                  */
   2483                 return -1;
   2484             }
   2485             try {
   2486                 for (;;) {
   2487                     int avail = canBlock ? Integer.MAX_VALUE : in.available();
   2488                     if (avail == 0) {
   2489                         return HEADER_BLOCKED;
   2490                     }
   2491 
   2492                     int tc = in.peek();
   2493                     switch (tc) {
   2494                         case TC_BLOCKDATA:
   2495                             if (avail < 2) {
   2496                                 return HEADER_BLOCKED;
   2497                             }
   2498                             in.readFully(hbuf, 0, 2);
   2499                             return hbuf[1] & 0xFF;
   2500 
   2501                         case TC_BLOCKDATALONG:
   2502                             if (avail < 5) {
   2503                                 return HEADER_BLOCKED;
   2504                             }
   2505                             in.readFully(hbuf, 0, 5);
   2506                             int len = Bits.getInt(hbuf, 1);
   2507                             if (len < 0) {
   2508                                 throw new StreamCorruptedException(
   2509                                     "illegal block data header length: " +
   2510                                     len);
   2511                             }
   2512                             return len;
   2513 
   2514                         /*
   2515                          * TC_RESETs may occur in between data blocks.
   2516                          * Unfortunately, this case must be parsed at a lower
   2517                          * level than other typecodes, since primitive data
   2518                          * reads may span data blocks separated by a TC_RESET.
   2519                          */
   2520                         case TC_RESET:
   2521                             in.read();
   2522                             handleReset();
   2523                             break;
   2524 
   2525                         default:
   2526                             if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
   2527                                 throw new StreamCorruptedException(
   2528                                     String.format("invalid type code: %02X",
   2529                                     tc));
   2530                             }
   2531                             return -1;
   2532                     }
   2533                 }
   2534             } catch (EOFException ex) {
   2535                 throw new StreamCorruptedException(
   2536                     "unexpected EOF while reading block data header");
   2537             }
   2538         }
   2539 
   2540         /**
   2541          * Refills internal buffer buf with block data.  Any data in buf at the
   2542          * time of the call is considered consumed.  Sets the pos, end, and
   2543          * unread fields to reflect the new amount of available block data; if
   2544          * the next element in the stream is not a data block, sets pos and
   2545          * unread to 0 and end to -1.
   2546          */
   2547         private void refill() throws IOException {
   2548             try {
   2549                 do {
   2550                     pos = 0;
   2551                     if (unread > 0) {
   2552                         int n =
   2553                             in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
   2554                         if (n >= 0) {
   2555                             end = n;
   2556                             unread -= n;
   2557                         } else {
   2558                             throw new StreamCorruptedException(
   2559                                 "unexpected EOF in middle of data block");
   2560                         }
   2561                     } else {
   2562                         int n = readBlockHeader(true);
   2563                         if (n >= 0) {
   2564                             end = 0;
   2565                             unread = n;
   2566                         } else {
   2567                             end = -1;
   2568                             unread = 0;
   2569                         }
   2570                     }
   2571                 } while (pos == end);
   2572             } catch (IOException ex) {
   2573                 pos = 0;
   2574                 end = -1;
   2575                 unread = 0;
   2576                 throw ex;
   2577             }
   2578         }
   2579 
   2580         /**
   2581          * If in block data mode, returns the number of unconsumed bytes
   2582          * remaining in the current data block.  If not in block data mode,
   2583          * throws an IllegalStateException.
   2584          */
   2585         int currentBlockRemaining() {
   2586             if (blkmode) {
   2587                 return (end >= 0) ? (end - pos) + unread : 0;
   2588             } else {
   2589                 throw new IllegalStateException();
   2590             }
   2591         }
   2592 
   2593         /**
   2594          * Peeks at (but does not consume) and returns the next byte value in
   2595          * the stream, or -1 if the end of the stream/block data (if in block
   2596          * data mode) has been reached.
   2597          */
   2598         int peek() throws IOException {
   2599             if (blkmode) {
   2600                 if (pos == end) {
   2601                     refill();
   2602                 }
   2603                 return (end >= 0) ? (buf[pos] & 0xFF) : -1;
   2604             } else {
   2605                 return in.peek();
   2606             }
   2607         }
   2608 
   2609         /**
   2610          * Peeks at (but does not consume) and returns the next byte value in
   2611          * the stream, or throws EOFException if end of stream/block data has
   2612          * been reached.
   2613          */
   2614         byte peekByte() throws IOException {
   2615             int val = peek();
   2616             if (val < 0) {
   2617                 throw new EOFException();
   2618             }
   2619             return (byte) val;
   2620         }
   2621 
   2622 
   2623         /* ----------------- generic input stream methods ------------------ */
   2624         /*
   2625          * The following methods are equivalent to their counterparts in
   2626          * InputStream, except that they interpret data block boundaries and
   2627          * read the requested data from within data blocks when in block data
   2628          * mode.
   2629          */
   2630 
   2631         public int read() throws IOException {
   2632             if (blkmode) {
   2633                 if (pos == end) {
   2634                     refill();
   2635                 }
   2636                 return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
   2637             } else {
   2638                 return in.read();
   2639             }
   2640         }
   2641 
   2642         public int read(byte[] b, int off, int len) throws IOException {
   2643             return read(b, off, len, false);
   2644         }
   2645 
   2646         public long skip(long len) throws IOException {
   2647             long remain = len;
   2648             while (remain > 0) {
   2649                 if (blkmode) {
   2650                     if (pos == end) {
   2651                         refill();
   2652                     }
   2653                     if (end < 0) {
   2654                         break;
   2655                     }
   2656                     int nread = (int) Math.min(remain, end - pos);
   2657                     remain -= nread;
   2658                     pos += nread;
   2659                 } else {
   2660                     int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
   2661                     if ((nread = in.read(buf, 0, nread)) < 0) {
   2662                         break;
   2663                     }
   2664                     remain -= nread;
   2665                 }
   2666             }
   2667             return len - remain;
   2668         }
   2669 
   2670         public int available() throws IOException {
   2671             if (blkmode) {
   2672                 if ((pos == end) && (unread == 0)) {
   2673                     int n;
   2674                     while ((n = readBlockHeader(false)) == 0) ;
   2675                     switch (n) {
   2676                         case HEADER_BLOCKED:
   2677                             break;
   2678 
   2679                         case -1:
   2680                             pos = 0;
   2681                             end = -1;
   2682                             break;
   2683 
   2684                         default:
   2685                             pos = 0;
   2686                             end = 0;
   2687                             unread = n;
   2688                             break;
   2689                     }
   2690                 }
   2691                 // avoid unnecessary call to in.available() if possible
   2692                 int unreadAvail = (unread > 0) ?
   2693                     Math.min(in.available(), unread) : 0;
   2694                 return (end >= 0) ? (end - pos) + unreadAvail : 0;
   2695             } else {
   2696                 return in.available();
   2697             }
   2698         }
   2699 
   2700         public void close() throws IOException {
   2701             if (blkmode) {
   2702                 pos = 0;
   2703                 end = -1;
   2704                 unread = 0;
   2705             }
   2706             in.close();
   2707         }
   2708 
   2709         /**
   2710          * Attempts to read len bytes into byte array b at offset off.  Returns
   2711          * the number of bytes read, or -1 if the end of stream/block data has
   2712          * been reached.  If copy is true, reads values into an intermediate
   2713          * buffer before copying them to b (to avoid exposing a reference to
   2714          * b).
   2715          */
   2716         int read(byte[] b, int off, int len, boolean copy) throws IOException {
   2717             if (len == 0) {
   2718                 return 0;
   2719             } else if (blkmode) {
   2720                 if (pos == end) {
   2721                     refill();
   2722                 }
   2723                 if (end < 0) {
   2724                     return -1;
   2725                 }
   2726                 int nread = Math.min(len, end - pos);
   2727                 System.arraycopy(buf, pos, b, off, nread);
   2728                 pos += nread;
   2729                 return nread;
   2730             } else if (copy) {
   2731                 int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
   2732                 if (nread > 0) {
   2733                     System.arraycopy(buf, 0, b, off, nread);
   2734                 }
   2735                 return nread;
   2736             } else {
   2737                 return in.read(b, off, len);
   2738             }
   2739         }
   2740 
   2741         /* ----------------- primitive data input methods ------------------ */
   2742         /*
   2743          * The following methods are equivalent to their counterparts in
   2744          * DataInputStream, except that they interpret data block boundaries
   2745          * and read the requested data from within data blocks when in block
   2746          * data mode.
   2747          */
   2748 
   2749         public void readFully(byte[] b) throws IOException {
   2750             readFully(b, 0, b.length, false);
   2751         }
   2752 
   2753         public void readFully(byte[] b, int off, int len) throws IOException {
   2754             readFully(b, off, len, false);
   2755         }
   2756 
   2757         public void readFully(byte[] b, int off, int len, boolean copy)
   2758             throws IOException
   2759         {
   2760             while (len > 0) {
   2761                 int n = read(b, off, len, copy);
   2762                 if (n < 0) {
   2763                     throw new EOFException();
   2764                 }
   2765                 off += n;
   2766                 len -= n;
   2767             }
   2768         }
   2769 
   2770         public int skipBytes(int n) throws IOException {
   2771             return din.skipBytes(n);
   2772         }
   2773 
   2774         public boolean readBoolean() throws IOException {
   2775             int v = read();
   2776             if (v < 0) {
   2777                 throw new EOFException();
   2778             }
   2779             return (v != 0);
   2780         }
   2781 
   2782         public byte readByte() throws IOException {
   2783             int v = read();
   2784             if (v < 0) {
   2785                 throw new EOFException();
   2786             }
   2787             return (byte) v;
   2788         }
   2789 
   2790         public int readUnsignedByte() throws IOException {
   2791             int v = read();
   2792             if (v < 0) {
   2793                 throw new EOFException();
   2794             }
   2795             return v;
   2796         }
   2797 
   2798         public char readChar() throws IOException {
   2799             if (!blkmode) {
   2800                 pos = 0;
   2801                 in.readFully(buf, 0, 2);
   2802             } else if (end - pos < 2) {
   2803                 return din.readChar();
   2804             }
   2805             char v = Bits.getChar(buf, pos);
   2806             pos += 2;
   2807             return v;
   2808         }
   2809 
   2810         public short readShort() throws IOException {
   2811             if (!blkmode) {
   2812                 pos = 0;
   2813                 in.readFully(buf, 0, 2);
   2814             } else if (end - pos < 2) {
   2815                 return din.readShort();
   2816             }
   2817             short v = Bits.getShort(buf, pos);
   2818             pos += 2;
   2819             return v;
   2820         }
   2821 
   2822         public int readUnsignedShort() throws IOException {
   2823             if (!blkmode) {
   2824                 pos = 0;
   2825                 in.readFully(buf, 0, 2);
   2826             } else if (end - pos < 2) {
   2827                 return din.readUnsignedShort();
   2828             }
   2829             int v = Bits.getShort(buf, pos) & 0xFFFF;
   2830             pos += 2;
   2831             return v;
   2832         }
   2833 
   2834         public int readInt() throws IOException {
   2835             if (!blkmode) {
   2836                 pos = 0;
   2837                 in.readFully(buf, 0, 4);
   2838             } else if (end - pos < 4) {
   2839                 return din.readInt();
   2840             }
   2841             int v = Bits.getInt(buf, pos);
   2842             pos += 4;
   2843             return v;
   2844         }
   2845 
   2846         public float readFloat() throws IOException {
   2847             if (!blkmode) {
   2848                 pos = 0;
   2849                 in.readFully(buf, 0, 4);
   2850             } else if (end - pos < 4) {
   2851                 return din.readFloat();
   2852             }
   2853             float v = Bits.getFloat(buf, pos);
   2854             pos += 4;
   2855             return v;
   2856         }
   2857 
   2858         public long readLong() throws IOException {
   2859             if (!blkmode) {
   2860                 pos = 0;
   2861                 in.readFully(buf, 0, 8);
   2862             } else if (end - pos < 8) {
   2863                 return din.readLong();
   2864             }
   2865             long v = Bits.getLong(buf, pos);
   2866             pos += 8;
   2867             return v;
   2868         }
   2869 
   2870         public double readDouble() throws IOException {
   2871             if (!blkmode) {
   2872                 pos = 0;
   2873                 in.readFully(buf, 0, 8);
   2874             } else if (end - pos < 8) {
   2875                 return din.readDouble();
   2876             }
   2877             double v = Bits.getDouble(buf, pos);
   2878             pos += 8;
   2879             return v;
   2880         }
   2881 
   2882         public String readUTF() throws IOException {
   2883             return readUTFBody(readUnsignedShort());
   2884         }
   2885 
   2886         @SuppressWarnings("deprecation")
   2887         public String readLine() throws IOException {
   2888             return din.readLine();      // deprecated, not worth optimizing
   2889         }
   2890 
   2891         /* -------------- primitive data array input methods --------------- */
   2892         /*
   2893          * The following methods read in spans of primitive data values.
   2894          * Though equivalent to calling the corresponding primitive read
   2895          * methods repeatedly, these methods are optimized for reading groups
   2896          * of primitive data values more efficiently.
   2897          */
   2898 
   2899         void readBooleans(boolean[] v, int off, int len) throws IOException {
   2900             int stop, endoff = off + len;
   2901             while (off < endoff) {
   2902                 if (!blkmode) {
   2903                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
   2904                     in.readFully(buf, 0, span);
   2905                     stop = off + span;
   2906                     pos = 0;
   2907                 } else if (end - pos < 1) {
   2908                     v[off++] = din.readBoolean();
   2909                     continue;
   2910                 } else {
   2911                     stop = Math.min(endoff, off + end - pos);
   2912                 }
   2913 
   2914                 while (off < stop) {
   2915                     v[off++] = Bits.getBoolean(buf, pos++);
   2916                 }
   2917             }
   2918         }
   2919 
   2920         void readChars(char[] v, int off, int len) throws IOException {
   2921             int stop, endoff = off + len;
   2922             while (off < endoff) {
   2923                 if (!blkmode) {
   2924                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
   2925                     in.readFully(buf, 0, span << 1);
   2926                     stop = off + span;
   2927                     pos = 0;
   2928                 } else if (end - pos < 2) {
   2929                     v[off++] = din.readChar();
   2930                     continue;
   2931                 } else {
   2932                     stop = Math.min(endoff, off + ((end - pos) >> 1));
   2933                 }
   2934 
   2935                 while (off < stop) {
   2936                     v[off++] = Bits.getChar(buf, pos);
   2937                     pos += 2;
   2938                 }
   2939             }
   2940         }
   2941 
   2942         void readShorts(short[] v, int off, int len) throws IOException {
   2943             int stop, endoff = off + len;
   2944             while (off < endoff) {
   2945                 if (!blkmode) {
   2946                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
   2947                     in.readFully(buf, 0, span << 1);
   2948                     stop = off + span;
   2949                     pos = 0;
   2950                 } else if (end - pos < 2) {
   2951                     v[off++] = din.readShort();
   2952                     continue;
   2953                 } else {
   2954                     stop = Math.min(endoff, off + ((end - pos) >> 1));
   2955                 }
   2956 
   2957                 while (off < stop) {
   2958                     v[off++] = Bits.getShort(buf, pos);
   2959                     pos += 2;
   2960                 }
   2961             }
   2962         }
   2963 
   2964         void readInts(int[] v, int off, int len) throws IOException {
   2965             int stop, endoff = off + len;
   2966             while (off < endoff) {
   2967                 if (!blkmode) {
   2968                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
   2969                     in.readFully(buf, 0, span << 2);
   2970                     stop = off + span;
   2971                     pos = 0;
   2972                 } else if (end - pos < 4) {
   2973                     v[off++] = din.readInt();
   2974                     continue;
   2975                 } else {
   2976                     stop = Math.min(endoff, off + ((end - pos) >> 2));
   2977                 }
   2978 
   2979                 while (off < stop) {
   2980                     v[off++] = Bits.getInt(buf, pos);
   2981                     pos += 4;
   2982                 }
   2983             }
   2984         }
   2985 
   2986         void readFloats(float[] v, int off, int len) throws IOException {
   2987             int span, endoff = off + len;
   2988             while (off < endoff) {
   2989                 if (!blkmode) {
   2990                     span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
   2991                     in.readFully(buf, 0, span << 2);
   2992                     pos = 0;
   2993                 } else if (end - pos < 4) {
   2994                     v[off++] = din.readFloat();
   2995                     continue;
   2996                 } else {
   2997                     span = Math.min(endoff - off, ((end - pos) >> 2));
   2998                 }
   2999 
   3000                 bytesToFloats(buf, pos, v, off, span);
   3001                 off += span;
   3002                 pos += span << 2;
   3003             }
   3004         }
   3005 
   3006         void readLongs(long[] v, int off, int len) throws IOException {
   3007             int stop, endoff = off + len;
   3008             while (off < endoff) {
   3009                 if (!blkmode) {
   3010                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
   3011                     in.readFully(buf, 0, span << 3);
   3012                     stop = off + span;
   3013                     pos = 0;
   3014                 } else if (end - pos < 8) {
   3015                     v[off++] = din.readLong();
   3016                     continue;
   3017                 } else {
   3018                     stop = Math.min(endoff, off + ((end - pos) >> 3));
   3019                 }
   3020 
   3021                 while (off < stop) {
   3022                     v[off++] = Bits.getLong(buf, pos);
   3023                     pos += 8;
   3024                 }
   3025             }
   3026         }
   3027 
   3028         void readDoubles(double[] v, int off, int len) throws IOException {
   3029             int span, endoff = off + len;
   3030             while (off < endoff) {
   3031                 if (!blkmode) {
   3032                     span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
   3033                     in.readFully(buf, 0, span << 3);
   3034                     pos = 0;
   3035                 } else if (end - pos < 8) {
   3036                     v[off++] = din.readDouble();
   3037                     continue;
   3038                 } else {
   3039                     span = Math.min(endoff - off, ((end - pos) >> 3));
   3040                 }
   3041 
   3042                 bytesToDoubles(buf, pos, v, off, span);
   3043                 off += span;
   3044                 pos += span << 3;
   3045             }
   3046         }
   3047 
   3048         /**
   3049          * Reads in string written in "long" UTF format.  "Long" UTF format is
   3050          * identical to standard UTF, except that it uses an 8 byte header
   3051          * (instead of the standard 2 bytes) to convey the UTF encoding length.
   3052          */
   3053         String readLongUTF() throws IOException {
   3054             return readUTFBody(readLong());
   3055         }
   3056 
   3057         /**
   3058          * Reads in the "body" (i.e., the UTF representation minus the 2-byte
   3059          * or 8-byte length header) of a UTF encoding, which occupies the next
   3060          * utflen bytes.
   3061          */
   3062         private String readUTFBody(long utflen) throws IOException {
   3063             StringBuilder sbuf = new StringBuilder();
   3064             if (!blkmode) {
   3065                 end = pos = 0;
   3066             }
   3067 
   3068             while (utflen > 0) {
   3069                 int avail = end - pos;
   3070                 if (avail >= 3 || (long) avail == utflen) {
   3071                     utflen -= readUTFSpan(sbuf, utflen);
   3072                 } else {
   3073                     if (blkmode) {
   3074                         // near block boundary, read one byte at a time
   3075                         utflen -= readUTFChar(sbuf, utflen);
   3076                     } else {
   3077                         // shift and refill buffer manually
   3078                         if (avail > 0) {
   3079                             System.arraycopy(buf, pos, buf, 0, avail);
   3080                         }
   3081                         pos = 0;
   3082                         end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
   3083                         in.readFully(buf, avail, end - avail);
   3084                     }
   3085                 }
   3086             }
   3087 
   3088             return sbuf.toString();
   3089         }
   3090 
   3091         /**
   3092          * Reads span of UTF-encoded characters out of internal buffer
   3093          * (starting at offset pos and ending at or before offset end),
   3094          * consuming no more than utflen bytes.  Appends read characters to
   3095          * sbuf.  Returns the number of bytes consumed.
   3096          */
   3097         private long readUTFSpan(StringBuilder sbuf, long utflen)
   3098             throws IOException
   3099         {
   3100             int cpos = 0;
   3101             int start = pos;
   3102             int avail = Math.min(end - pos, CHAR_BUF_SIZE);
   3103             // stop short of last char unless all of utf bytes in buffer
   3104             int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
   3105             boolean outOfBounds = false;
   3106 
   3107             try {
   3108                 while (pos < stop) {
   3109                     int b1, b2, b3;
   3110                     b1 = buf[pos++] & 0xFF;
   3111                     switch (b1 >> 4) {
   3112                         case 0:
   3113                         case 1:
   3114                         case 2:
   3115                         case 3:
   3116                         case 4:
   3117                         case 5:
   3118                         case 6:
   3119                         case 7:   // 1 byte format: 0xxxxxxx
   3120                             cbuf[cpos++] = (char) b1;
   3121                             break;
   3122 
   3123                         case 12:
   3124                         case 13:  // 2 byte format: 110xxxxx 10xxxxxx
   3125                             b2 = buf[pos++];
   3126                             if ((b2 & 0xC0) != 0x80) {
   3127                                 throw new UTFDataFormatException();
   3128                             }
   3129                             cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
   3130                                                    ((b2 & 0x3F) << 0));
   3131                             break;
   3132 
   3133                         case 14:  // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
   3134                             b3 = buf[pos + 1];
   3135                             b2 = buf[pos + 0];
   3136                             pos += 2;
   3137                             if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
   3138                                 throw new UTFDataFormatException();
   3139                             }
   3140                             cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
   3141                                                    ((b2 & 0x3F) << 6) |
   3142                                                    ((b3 & 0x3F) << 0));
   3143                             break;
   3144 
   3145                         default:  // 10xx xxxx, 1111 xxxx
   3146                             throw new UTFDataFormatException();
   3147                     }
   3148                 }
   3149             } catch (ArrayIndexOutOfBoundsException ex) {
   3150                 outOfBounds = true;
   3151             } finally {
   3152                 if (outOfBounds || (pos - start) > utflen) {
   3153                     /*
   3154                      * Fix for 4450867: if a malformed utf char causes the
   3155                      * conversion loop to scan past the expected end of the utf
   3156                      * string, only consume the expected number of utf bytes.
   3157                      */
   3158                     pos = start + (int) utflen;
   3159                     throw new UTFDataFormatException();
   3160                 }
   3161             }
   3162 
   3163             sbuf.append(cbuf, 0, cpos);
   3164             return pos - start;
   3165         }
   3166 
   3167         /**
   3168          * Reads in single UTF-encoded character one byte at a time, appends
   3169          * the character to sbuf, and returns the number of bytes consumed.
   3170          * This method is used when reading in UTF strings written in block
   3171          * data mode to handle UTF-encoded characters which (potentially)
   3172          * straddle block-data boundaries.
   3173          */
   3174         private int readUTFChar(StringBuilder sbuf, long utflen)
   3175             throws IOException
   3176         {
   3177             int b1, b2, b3;
   3178             b1 = readByte() & 0xFF;
   3179             switch (b1 >> 4) {
   3180                 case 0:
   3181                 case 1:
   3182                 case 2:
   3183                 case 3:
   3184                 case 4:
   3185                 case 5:
   3186                 case 6:
   3187                 case 7:     // 1 byte format: 0xxxxxxx
   3188                     sbuf.append((char) b1);
   3189                     return 1;
   3190 
   3191                 case 12:
   3192                 case 13:    // 2 byte format: 110xxxxx 10xxxxxx
   3193                     if (utflen < 2) {
   3194                         throw new UTFDataFormatException();
   3195                     }
   3196                     b2 = readByte();
   3197                     if ((b2 & 0xC0) != 0x80) {
   3198                         throw new UTFDataFormatException();
   3199                     }
   3200                     sbuf.append((char) (((b1 & 0x1F) << 6) |
   3201                                         ((b2 & 0x3F) << 0)));
   3202                     return 2;
   3203 
   3204                 case 14:    // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
   3205                     if (utflen < 3) {
   3206                         if (utflen == 2) {
   3207                             readByte();         // consume remaining byte
   3208                         }
   3209                         throw new UTFDataFormatException();
   3210                     }
   3211                     b2 = readByte();
   3212                     b3 = readByte();
   3213                     if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
   3214                         throw new UTFDataFormatException();
   3215                     }
   3216                     sbuf.append((char) (((b1 & 0x0F) << 12) |
   3217                                         ((b2 & 0x3F) << 6) |
   3218                                         ((b3 & 0x3F) << 0)));
   3219                     return 3;
   3220 
   3221                 default:   // 10xx xxxx, 1111 xxxx
   3222                     throw new UTFDataFormatException();
   3223             }
   3224         }
   3225     }
   3226 
   3227     /**
   3228      * Unsynchronized table which tracks wire handle to object mappings, as
   3229      * well as ClassNotFoundExceptions associated with deserialized objects.
   3230      * This class implements an exception-propagation algorithm for
   3231      * determining which objects should have ClassNotFoundExceptions associated
   3232      * with them, taking into account cycles and discontinuities (e.g., skipped
   3233      * fields) in the object graph.
   3234      *
   3235      * <p>General use of the table is as follows: during deserialization, a
   3236      * given object is first assigned a handle by calling the assign method.
   3237      * This method leaves the assigned handle in an "open" state, wherein
   3238      * dependencies on the exception status of other handles can be registered
   3239      * by calling the markDependency method, or an exception can be directly
   3240      * associated with the handle by calling markException.  When a handle is
   3241      * tagged with an exception, the HandleTable assumes responsibility for
   3242      * propagating the exception to any other objects which depend
   3243      * (transitively) on the exception-tagged object.
   3244      *
   3245      * <p>Once all exception information/dependencies for the handle have been
   3246      * registered, the handle should be "closed" by calling the finish method
   3247      * on it.  The act of finishing a handle allows the exception propagation
   3248      * algorithm to aggressively prune dependency links, lessening the
   3249      * performance/memory impact of exception tracking.
   3250      *
   3251      * <p>Note that the exception propagation algorithm used depends on handles
   3252      * being assigned/finished in LIFO order; however, for simplicity as well
   3253      * as memory conservation, it does not enforce this constraint.
   3254      */
   3255     // REMIND: add full description of exception propagation algorithm?
   3256     private static class HandleTable {
   3257 
   3258         /* status codes indicating whether object has associated exception */
   3259         private static final byte STATUS_OK = 1;
   3260         private static final byte STATUS_UNKNOWN = 2;
   3261         private static final byte STATUS_EXCEPTION = 3;
   3262 
   3263         /** array mapping handle -> object status */
   3264         byte[] status;
   3265         /** array mapping handle -> object/exception (depending on status) */
   3266         Object[] entries;
   3267         /** array mapping handle -> list of dependent handles (if any) */
   3268         HandleList[] deps;
   3269         /** lowest unresolved dependency */
   3270         int lowDep = -1;
   3271         /** number of handles in table */
   3272         int size = 0;
   3273 
   3274         /**
   3275          * Creates handle table with the given initial capacity.
   3276          */
   3277         HandleTable(int initialCapacity) {
   3278             status = new byte[initialCapacity];
   3279             entries = new Object[initialCapacity];
   3280             deps = new HandleList[initialCapacity];
   3281         }
   3282 
   3283         /**
   3284          * Assigns next available handle to given object, and returns assigned
   3285          * handle.  Once object has been completely deserialized (and all
   3286          * dependencies on other objects identified), the handle should be
   3287          * "closed" by passing it to finish().
   3288          */
   3289         int assign(Object obj) {
   3290             if (size >= entries.length) {
   3291                 grow();
   3292             }
   3293             status[size] = STATUS_UNKNOWN;
   3294             entries[size] = obj;
   3295             return size++;
   3296         }
   3297 
   3298         /**
   3299          * Registers a dependency (in exception status) of one handle on
   3300          * another.  The dependent handle must be "open" (i.e., assigned, but
   3301          * not finished yet).  No action is taken if either dependent or target
   3302          * handle is NULL_HANDLE.
   3303          */
   3304         void markDependency(int dependent, int target) {
   3305             if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
   3306                 return;
   3307             }
   3308             switch (status[dependent]) {
   3309 
   3310                 case STATUS_UNKNOWN:
   3311                     switch (status[target]) {
   3312                         case STATUS_OK:
   3313                             // ignore dependencies on objs with no exception
   3314                             break;
   3315 
   3316                         case STATUS_EXCEPTION:
   3317                             // eagerly propagate exception
   3318                             markException(dependent,
   3319                                 (ClassNotFoundException) entries[target]);
   3320                             break;
   3321 
   3322                         case STATUS_UNKNOWN:
   3323                             // add to dependency list of target
   3324                             if (deps[target] == null) {
   3325                                 deps[target] = new HandleList();
   3326                             }
   3327                             deps[target].add(dependent);
   3328 
   3329                             // remember lowest unresolved target seen
   3330                             if (lowDep < 0 || lowDep > target) {
   3331                                 lowDep = target;
   3332                             }
   3333                             break;
   3334 
   3335                         default:
   3336                             throw new InternalError();
   3337                     }
   3338                     break;
   3339 
   3340                 case STATUS_EXCEPTION:
   3341                     break;
   3342 
   3343                 default:
   3344                     throw new InternalError();
   3345             }
   3346         }
   3347 
   3348         /**
   3349          * Associates a ClassNotFoundException (if one not already associated)
   3350          * with the currently active handle and propagates it to other
   3351          * referencing objects as appropriate.  The specified handle must be
   3352          * "open" (i.e., assigned, but not finished yet).
   3353          */
   3354         void markException(int handle, ClassNotFoundException ex) {
   3355             switch (status[handle]) {
   3356                 case STATUS_UNKNOWN:
   3357                     status[handle] = STATUS_EXCEPTION;
   3358                     entries[handle] = ex;
   3359 
   3360                     // propagate exception to dependents
   3361                     HandleList dlist = deps[handle];
   3362                     if (dlist != null) {
   3363                         int ndeps = dlist.size();
   3364                         for (int i = 0; i < ndeps; i++) {
   3365                             markException(dlist.get(i), ex);
   3366                         }
   3367                         deps[handle] = null;
   3368                     }
   3369                     break;
   3370 
   3371                 case STATUS_EXCEPTION:
   3372                     break;
   3373 
   3374                 default:
   3375                     throw new InternalError();
   3376             }
   3377         }
   3378 
   3379         /**
   3380          * Marks given handle as finished, meaning that no new dependencies
   3381          * will be marked for handle.  Calls to the assign and finish methods
   3382          * must occur in LIFO order.
   3383          */
   3384         void finish(int handle) {
   3385             int end;
   3386             if (lowDep < 0) {
   3387                 // no pending unknowns, only resolve current handle
   3388                 end = handle + 1;
   3389             } else if (lowDep >= handle) {
   3390                 // pending unknowns now clearable, resolve all upward handles
   3391                 end = size;
   3392                 lowDep = -1;
   3393             } else {
   3394                 // unresolved backrefs present, can't resolve anything yet
   3395                 return;
   3396             }
   3397 
   3398             // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
   3399             for (int i = handle; i < end; i++) {
   3400                 switch (status[i]) {
   3401                     case STATUS_UNKNOWN:
   3402                         status[i] = STATUS_OK;
   3403                         deps[i] = null;
   3404                         break;
   3405 
   3406                     case STATUS_OK:
   3407                     case STATUS_EXCEPTION:
   3408                         break;
   3409 
   3410                     default:
   3411                         throw new InternalError();
   3412                 }
   3413             }
   3414         }
   3415 
   3416         /**
   3417          * Assigns a new object to the given handle.  The object previously
   3418          * associated with the handle is forgotten.  This method has no effect
   3419          * if the given handle already has an exception associated with it.
   3420          * This method may be called at any time after the handle is assigned.
   3421          */
   3422         void setObject(int handle, Object obj) {
   3423             switch (status[handle]) {
   3424                 case STATUS_UNKNOWN:
   3425                 case STATUS_OK:
   3426                     entries[handle] = obj;
   3427                     break;
   3428 
   3429                 case STATUS_EXCEPTION:
   3430                     break;
   3431 
   3432                 default:
   3433                     throw new InternalError();
   3434             }
   3435         }
   3436 
   3437         /**
   3438          * Looks up and returns object associated with the given handle.
   3439          * Returns null if the given handle is NULL_HANDLE, or if it has an
   3440          * associated ClassNotFoundException.
   3441          */
   3442         Object lookupObject(int handle) {
   3443             return (handle != NULL_HANDLE &&
   3444                     status[handle] != STATUS_EXCEPTION) ?
   3445                 entries[handle] : null;
   3446         }
   3447 
   3448         /**
   3449          * Looks up and returns ClassNotFoundException associated with the
   3450          * given handle.  Returns null if the given handle is NULL_HANDLE, or
   3451          * if there is no ClassNotFoundException associated with the handle.
   3452          */
   3453         ClassNotFoundException lookupException(int handle) {
   3454             return (handle != NULL_HANDLE &&
   3455                     status[handle] == STATUS_EXCEPTION) ?
   3456                 (ClassNotFoundException) entries[handle] : null;
   3457         }
   3458 
   3459         /**
   3460          * Resets table to its initial state.
   3461          */
   3462         void clear() {
   3463             Arrays.fill(status, 0, size, (byte) 0);
   3464             Arrays.fill(entries, 0, size, null);
   3465             Arrays.fill(deps, 0, size, null);
   3466             lowDep = -1;
   3467             size = 0;
   3468         }
   3469 
   3470         /**
   3471          * Returns number of handles registered in table.
   3472          */
   3473         int size() {
   3474             return size;
   3475         }
   3476 
   3477         /**
   3478          * Expands capacity of internal arrays.
   3479          */
   3480         private void grow() {
   3481             int newCapacity = (entries.length << 1) + 1;
   3482 
   3483             byte[] newStatus = new byte[newCapacity];
   3484             Object[] newEntries = new Object[newCapacity];
   3485             HandleList[] newDeps = new HandleList[newCapacity];
   3486 
   3487             System.arraycopy(status, 0, newStatus, 0, size);
   3488             System.arraycopy(entries, 0, newEntries, 0, size);
   3489             System.arraycopy(deps, 0, newDeps, 0, size);
   3490 
   3491             status = newStatus;
   3492             entries = newEntries;
   3493             deps = newDeps;
   3494         }
   3495 
   3496         /**
   3497          * Simple growable list of (integer) handles.
   3498          */
   3499         private static class HandleList {
   3500             private int[] list = new int[4];
   3501             private int size = 0;
   3502 
   3503             public HandleList() {
   3504             }
   3505 
   3506             public void add(int handle) {
   3507                 if (size >= list.length) {
   3508                     int[] newList = new int[list.length << 1];
   3509                     System.arraycopy(list, 0, newList, 0, list.length);
   3510                     list = newList;
   3511                 }
   3512                 list[size++] = handle;
   3513             }
   3514 
   3515             public int get(int index) {
   3516                 if (index >= size) {
   3517                     throw new ArrayIndexOutOfBoundsException();
   3518                 }
   3519                 return list[index];
   3520             }
   3521 
   3522             public int size() {
   3523                 return size;
   3524             }
   3525         }
   3526     }
   3527 
   3528     /**
   3529      * Method for cloning arrays in case of using unsharing reading
   3530      */
   3531     private static Object cloneArray(Object array) {
   3532         if (array instanceof Object[]) {
   3533             return ((Object[]) array).clone();
   3534         } else if (array instanceof boolean[]) {
   3535             return ((boolean[]) array).clone();
   3536         } else if (array instanceof byte[]) {
   3537             return ((byte[]) array).clone();
   3538         } else if (array instanceof char[]) {
   3539             return ((char[]) array).clone();
   3540         } else if (array instanceof double[]) {
   3541             return ((double[]) array).clone();
   3542         } else if (array instanceof float[]) {
   3543             return ((float[]) array).clone();
   3544         } else if (array instanceof int[]) {
   3545             return ((int[]) array).clone();
   3546         } else if (array instanceof long[]) {
   3547             return ((long[]) array).clone();
   3548         } else if (array instanceof short[]) {
   3549             return ((short[]) array).clone();
   3550         } else {
   3551             throw new AssertionError();
   3552         }
   3553     }
   3554 
   3555 }
   3556