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