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