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