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