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