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