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