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