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