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