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