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