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