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