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