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