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