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