emul/compact/src/main/java/java/io/ObjectInputStream.java
brancharithmetic
changeset 774 42bc1e89134d
parent 755 5652acd48509
parent 773 406faa8bc64f
child 778 6f8683517f1f
     1.1 --- a/emul/compact/src/main/java/java/io/ObjectInputStream.java	Mon Feb 25 19:00:08 2013 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,3357 +0,0 @@
     1.4 -/*
     1.5 - * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
     1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 - *
     1.8 - * This code is free software; you can redistribute it and/or modify it
     1.9 - * under the terms of the GNU General Public License version 2 only, as
    1.10 - * published by the Free Software Foundation.  Oracle designates this
    1.11 - * particular file as subject to the "Classpath" exception as provided
    1.12 - * by Oracle in the LICENSE file that accompanied this code.
    1.13 - *
    1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 - * version 2 for more details (a copy is included in the LICENSE file that
    1.18 - * accompanied this code).
    1.19 - *
    1.20 - * You should have received a copy of the GNU General Public License version
    1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 - *
    1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 - * or visit www.oracle.com if you need additional information or have any
    1.26 - * questions.
    1.27 - */
    1.28 -
    1.29 -package java.io;
    1.30 -
    1.31 -import java.lang.reflect.Array;
    1.32 -import java.lang.reflect.Modifier;
    1.33 -import java.lang.reflect.Proxy;
    1.34 -import java.util.Arrays;
    1.35 -import java.util.HashMap;
    1.36 -import org.apidesign.bck2brwsr.emul.lang.System;
    1.37 -
    1.38 -/**
    1.39 - * An ObjectInputStream deserializes primitive data and objects previously
    1.40 - * written using an ObjectOutputStream.
    1.41 - *
    1.42 - * <p>ObjectOutputStream and ObjectInputStream can provide an application with
    1.43 - * persistent storage for graphs of objects when used with a FileOutputStream
    1.44 - * and FileInputStream respectively.  ObjectInputStream is used to recover
    1.45 - * those objects previously serialized. Other uses include passing objects
    1.46 - * between hosts using a socket stream or for marshaling and unmarshaling
    1.47 - * arguments and parameters in a remote communication system.
    1.48 - *
    1.49 - * <p>ObjectInputStream ensures that the types of all objects in the graph
    1.50 - * created from the stream match the classes present in the Java Virtual
    1.51 - * Machine.  Classes are loaded as required using the standard mechanisms.
    1.52 - *
    1.53 - * <p>Only objects that support the java.io.Serializable or
    1.54 - * java.io.Externalizable interface can be read from streams.
    1.55 - *
    1.56 - * <p>The method <code>readObject</code> is used to read an object from the
    1.57 - * stream.  Java's safe casting should be used to get the desired type.  In
    1.58 - * Java, strings and arrays are objects and are treated as objects during
    1.59 - * serialization. When read they need to be cast to the expected type.
    1.60 - *
    1.61 - * <p>Primitive data types can be read from the stream using the appropriate
    1.62 - * method on DataInput.
    1.63 - *
    1.64 - * <p>The default deserialization mechanism for objects restores the contents
    1.65 - * of each field to the value and type it had when it was written.  Fields
    1.66 - * declared as transient or static are ignored by the deserialization process.
    1.67 - * References to other objects cause those objects to be read from the stream
    1.68 - * as necessary.  Graphs of objects are restored correctly using a reference
    1.69 - * sharing mechanism.  New objects are always allocated when deserializing,
    1.70 - * which prevents existing objects from being overwritten.
    1.71 - *
    1.72 - * <p>Reading an object is analogous to running the constructors of a new
    1.73 - * object.  Memory is allocated for the object and initialized to zero (NULL).
    1.74 - * No-arg constructors are invoked for the non-serializable classes and then
    1.75 - * the fields of the serializable classes are restored from the stream starting
    1.76 - * with the serializable class closest to java.lang.object and finishing with
    1.77 - * the object's most specific class.
    1.78 - *
    1.79 - * <p>For example to read from a stream as written by the example in
    1.80 - * ObjectOutputStream:
    1.81 - * <br>
    1.82 - * <pre>
    1.83 - *      FileInputStream fis = new FileInputStream("t.tmp");
    1.84 - *      ObjectInputStream ois = new ObjectInputStream(fis);
    1.85 - *
    1.86 - *      int i = ois.readInt();
    1.87 - *      String today = (String) ois.readObject();
    1.88 - *      Date date = (Date) ois.readObject();
    1.89 - *
    1.90 - *      ois.close();
    1.91 - * </pre>
    1.92 - *
    1.93 - * <p>Classes control how they are serialized by implementing either the
    1.94 - * java.io.Serializable or java.io.Externalizable interfaces.
    1.95 - *
    1.96 - * <p>Implementing the Serializable interface allows object serialization to
    1.97 - * save and restore the entire state of the object and it allows classes to
    1.98 - * evolve between the time the stream is written and the time it is read.  It
    1.99 - * automatically traverses references between objects, saving and restoring
   1.100 - * entire graphs.
   1.101 - *
   1.102 - * <p>Serializable classes that require special handling during the
   1.103 - * serialization and deserialization process should implement the following
   1.104 - * methods:<p>
   1.105 - *
   1.106 - * <pre>
   1.107 - * private void writeObject(java.io.ObjectOutputStream stream)
   1.108 - *     throws IOException;
   1.109 - * private void readObject(java.io.ObjectInputStream stream)
   1.110 - *     throws IOException, ClassNotFoundException;
   1.111 - * private void readObjectNoData()
   1.112 - *     throws ObjectStreamException;
   1.113 - * </pre>
   1.114 - *
   1.115 - * <p>The readObject method is responsible for reading and restoring the state
   1.116 - * of the object for its particular class using data written to the stream by
   1.117 - * the corresponding writeObject method.  The method does not need to concern
   1.118 - * itself with the state belonging to its superclasses or subclasses.  State is
   1.119 - * restored by reading data from the ObjectInputStream for the individual
   1.120 - * fields and making assignments to the appropriate fields of the object.
   1.121 - * Reading primitive data types is supported by DataInput.
   1.122 - *
   1.123 - * <p>Any attempt to read object data which exceeds the boundaries of the
   1.124 - * custom data written by the corresponding writeObject method will cause an
   1.125 - * OptionalDataException to be thrown with an eof field value of true.
   1.126 - * Non-object reads which exceed the end of the allotted data will reflect the
   1.127 - * end of data in the same way that they would indicate the end of the stream:
   1.128 - * bytewise reads will return -1 as the byte read or number of bytes read, and
   1.129 - * primitive reads will throw EOFExceptions.  If there is no corresponding
   1.130 - * writeObject method, then the end of default serialized data marks the end of
   1.131 - * the allotted data.
   1.132 - *
   1.133 - * <p>Primitive and object read calls issued from within a readExternal method
   1.134 - * behave in the same manner--if the stream is already positioned at the end of
   1.135 - * data written by the corresponding writeExternal method, object reads will
   1.136 - * throw OptionalDataExceptions with eof set to true, bytewise reads will
   1.137 - * return -1, and primitive reads will throw EOFExceptions.  Note that this
   1.138 - * behavior does not hold for streams written with the old
   1.139 - * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
   1.140 - * end of data written by writeExternal methods is not demarcated, and hence
   1.141 - * cannot be detected.
   1.142 - *
   1.143 - * <p>The readObjectNoData method is responsible for initializing the state of
   1.144 - * the object for its particular class in the event that the serialization
   1.145 - * stream does not list the given class as a superclass of the object being
   1.146 - * deserialized.  This may occur in cases where the receiving party uses a
   1.147 - * different version of the deserialized instance's class than the sending
   1.148 - * party, and the receiver's version extends classes that are not extended by
   1.149 - * the sender's version.  This may also occur if the serialization stream has
   1.150 - * been tampered; hence, readObjectNoData is useful for initializing
   1.151 - * deserialized objects properly despite a "hostile" or incomplete source
   1.152 - * stream.
   1.153 - *
   1.154 - * <p>Serialization does not read or assign values to the fields of any object
   1.155 - * that does not implement the java.io.Serializable interface.  Subclasses of
   1.156 - * Objects that are not serializable can be serializable. In this case the
   1.157 - * non-serializable class must have a no-arg constructor to allow its fields to
   1.158 - * be initialized.  In this case it is the responsibility of the subclass to
   1.159 - * save and restore the state of the non-serializable class. It is frequently
   1.160 - * the case that the fields of that class are accessible (public, package, or
   1.161 - * protected) or that there are get and set methods that can be used to restore
   1.162 - * the state.
   1.163 - *
   1.164 - * <p>Any exception that occurs while deserializing an object will be caught by
   1.165 - * the ObjectInputStream and abort the reading process.
   1.166 - *
   1.167 - * <p>Implementing the Externalizable interface allows the object to assume
   1.168 - * complete control over the contents and format of the object's serialized
   1.169 - * form.  The methods of the Externalizable interface, writeExternal and
   1.170 - * readExternal, are called to save and restore the objects state.  When
   1.171 - * implemented by a class they can write and read their own state using all of
   1.172 - * the methods of ObjectOutput and ObjectInput.  It is the responsibility of
   1.173 - * the objects to handle any versioning that occurs.
   1.174 - *
   1.175 - * <p>Enum constants are deserialized differently than ordinary serializable or
   1.176 - * externalizable objects.  The serialized form of an enum constant consists
   1.177 - * solely of its name; field values of the constant are not transmitted.  To
   1.178 - * deserialize an enum constant, ObjectInputStream reads the constant name from
   1.179 - * the stream; the deserialized constant is then obtained by calling the static
   1.180 - * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
   1.181 - * base type and the received constant name as arguments.  Like other
   1.182 - * serializable or externalizable objects, enum constants can function as the
   1.183 - * targets of back references appearing subsequently in the serialization
   1.184 - * stream.  The process by which enum constants are deserialized cannot be
   1.185 - * customized: any class-specific readObject, readObjectNoData, and readResolve
   1.186 - * methods defined by enum types are ignored during deserialization.
   1.187 - * Similarly, any serialPersistentFields or serialVersionUID field declarations
   1.188 - * are also ignored--all enum types have a fixed serialVersionUID of 0L.
   1.189 - *
   1.190 - * @author      Mike Warres
   1.191 - * @author      Roger Riggs
   1.192 - * @see java.io.DataInput
   1.193 - * @see java.io.ObjectOutputStream
   1.194 - * @see java.io.Serializable
   1.195 - * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
   1.196 - * @since   JDK1.1
   1.197 - */
   1.198 -public class ObjectInputStream
   1.199 -    extends InputStream implements ObjectInput, ObjectStreamConstants
   1.200 -{
   1.201 -    /** handle value representing null */
   1.202 -    private static final int NULL_HANDLE = -1;
   1.203 -
   1.204 -    /** marker for unshared objects in internal handle table */
   1.205 -    private static final Object unsharedMarker = new Object();
   1.206 -
   1.207 -    /** table mapping primitive type names to corresponding class objects */
   1.208 -    private static final HashMap<String, Class<?>> primClasses
   1.209 -        = new HashMap<>(8, 1.0F);
   1.210 -    static {
   1.211 -        primClasses.put("boolean", boolean.class);
   1.212 -        primClasses.put("byte", byte.class);
   1.213 -        primClasses.put("char", char.class);
   1.214 -        primClasses.put("short", short.class);
   1.215 -        primClasses.put("int", int.class);
   1.216 -        primClasses.put("long", long.class);
   1.217 -        primClasses.put("float", float.class);
   1.218 -        primClasses.put("double", double.class);
   1.219 -        primClasses.put("void", void.class);
   1.220 -    }
   1.221 -
   1.222 -    /** filter stream for handling block data conversion */
   1.223 -    private final BlockDataInputStream bin;
   1.224 -    /** validation callback list */
   1.225 -    private final ValidationList vlist;
   1.226 -    /** recursion depth */
   1.227 -    private int depth;
   1.228 -    /** whether stream is closed */
   1.229 -    private boolean closed;
   1.230 -
   1.231 -    /** wire handle -> obj/exception map */
   1.232 -    private final HandleTable handles;
   1.233 -    /** scratch field for passing handle values up/down call stack */
   1.234 -    private int passHandle = NULL_HANDLE;
   1.235 -    /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
   1.236 -    private boolean defaultDataEnd = false;
   1.237 -
   1.238 -    /** buffer for reading primitive field values */
   1.239 -    private byte[] primVals;
   1.240 -
   1.241 -    /** if true, invoke readObjectOverride() instead of readObject() */
   1.242 -    private final boolean enableOverride;
   1.243 -    /** if true, invoke resolveObject() */
   1.244 -    private boolean enableResolve;
   1.245 -
   1.246 -    /**
   1.247 -     * Context during upcalls to class-defined readObject methods; holds
   1.248 -     * object currently being deserialized and descriptor for current class.
   1.249 -     * Null when not during readObject upcall.
   1.250 -     */
   1.251 -    private Object curContext;
   1.252 -
   1.253 -    /**
   1.254 -     * Creates an ObjectInputStream that reads from the specified InputStream.
   1.255 -     * A serialization stream header is read from the stream and verified.
   1.256 -     * This constructor will block until the corresponding ObjectOutputStream
   1.257 -     * has written and flushed the header.
   1.258 -     *
   1.259 -     * <p>If a security manager is installed, this constructor will check for
   1.260 -     * the "enableSubclassImplementation" SerializablePermission when invoked
   1.261 -     * directly or indirectly by the constructor of a subclass which overrides
   1.262 -     * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
   1.263 -     * methods.
   1.264 -     *
   1.265 -     * @param   in input stream to read from
   1.266 -     * @throws  StreamCorruptedException if the stream header is incorrect
   1.267 -     * @throws  IOException if an I/O error occurs while reading stream header
   1.268 -     * @throws  SecurityException if untrusted subclass illegally overrides
   1.269 -     *          security-sensitive methods
   1.270 -     * @throws  NullPointerException if <code>in</code> is <code>null</code>
   1.271 -     * @see     ObjectInputStream#ObjectInputStream()
   1.272 -     * @see     ObjectInputStream#readFields()
   1.273 -     * @see     ObjectOutputStream#ObjectOutputStream(OutputStream)
   1.274 -     */
   1.275 -    public ObjectInputStream(InputStream in) throws IOException {
   1.276 -        verifySubclass();
   1.277 -        bin = new BlockDataInputStream(in);
   1.278 -        handles = new HandleTable(10);
   1.279 -        vlist = new ValidationList();
   1.280 -        enableOverride = false;
   1.281 -        readStreamHeader();
   1.282 -        bin.setBlockDataMode(true);
   1.283 -    }
   1.284 -
   1.285 -    /**
   1.286 -     * Provide a way for subclasses that are completely reimplementing
   1.287 -     * ObjectInputStream to not have to allocate private data just used by this
   1.288 -     * implementation of ObjectInputStream.
   1.289 -     *
   1.290 -     * <p>If there is a security manager installed, this method first calls the
   1.291 -     * security manager's <code>checkPermission</code> method with the
   1.292 -     * <code>SerializablePermission("enableSubclassImplementation")</code>
   1.293 -     * permission to ensure it's ok to enable subclassing.
   1.294 -     *
   1.295 -     * @throws  SecurityException if a security manager exists and its
   1.296 -     *          <code>checkPermission</code> method denies enabling
   1.297 -     *          subclassing.
   1.298 -     * @see SecurityManager#checkPermission
   1.299 -     * @see java.io.SerializablePermission
   1.300 -     */
   1.301 -    protected ObjectInputStream() throws IOException, SecurityException {
   1.302 -        throw new SecurityException();
   1.303 -    }
   1.304 -
   1.305 -    /**
   1.306 -     * Read an object from the ObjectInputStream.  The class of the object, the
   1.307 -     * signature of the class, and the values of the non-transient and
   1.308 -     * non-static fields of the class and all of its supertypes are read.
   1.309 -     * Default deserializing for a class can be overriden using the writeObject
   1.310 -     * and readObject methods.  Objects referenced by this object are read
   1.311 -     * transitively so that a complete equivalent graph of objects is
   1.312 -     * reconstructed by readObject.
   1.313 -     *
   1.314 -     * <p>The root object is completely restored when all of its fields and the
   1.315 -     * objects it references are completely restored.  At this point the object
   1.316 -     * validation callbacks are executed in order based on their registered
   1.317 -     * priorities. The callbacks are registered by objects (in the readObject
   1.318 -     * special methods) as they are individually restored.
   1.319 -     *
   1.320 -     * <p>Exceptions are thrown for problems with the InputStream and for
   1.321 -     * classes that should not be deserialized.  All exceptions are fatal to
   1.322 -     * the InputStream and leave it in an indeterminate state; it is up to the
   1.323 -     * caller to ignore or recover the stream state.
   1.324 -     *
   1.325 -     * @throws  ClassNotFoundException Class of a serialized object cannot be
   1.326 -     *          found.
   1.327 -     * @throws  InvalidClassException Something is wrong with a class used by
   1.328 -     *          serialization.
   1.329 -     * @throws  StreamCorruptedException Control information in the
   1.330 -     *          stream is inconsistent.
   1.331 -     * @throws  OptionalDataException Primitive data was found in the
   1.332 -     *          stream instead of objects.
   1.333 -     * @throws  IOException Any of the usual Input/Output related exceptions.
   1.334 -     */
   1.335 -    public final Object readObject()
   1.336 -        throws IOException, ClassNotFoundException
   1.337 -    {
   1.338 -        throw new IOException();
   1.339 -    }
   1.340 -
   1.341 -    /**
   1.342 -     * This method is called by trusted subclasses of ObjectOutputStream that
   1.343 -     * constructed ObjectOutputStream using the protected no-arg constructor.
   1.344 -     * The subclass is expected to provide an override method with the modifier
   1.345 -     * "final".
   1.346 -     *
   1.347 -     * @return  the Object read from the stream.
   1.348 -     * @throws  ClassNotFoundException Class definition of a serialized object
   1.349 -     *          cannot be found.
   1.350 -     * @throws  OptionalDataException Primitive data was found in the stream
   1.351 -     *          instead of objects.
   1.352 -     * @throws  IOException if I/O errors occurred while reading from the
   1.353 -     *          underlying stream
   1.354 -     * @see #ObjectInputStream()
   1.355 -     * @see #readObject()
   1.356 -     * @since 1.2
   1.357 -     */
   1.358 -    protected Object readObjectOverride()
   1.359 -        throws IOException, ClassNotFoundException
   1.360 -    {
   1.361 -        return null;
   1.362 -    }
   1.363 -
   1.364 -    /**
   1.365 -     * Reads an "unshared" object from the ObjectInputStream.  This method is
   1.366 -     * identical to readObject, except that it prevents subsequent calls to
   1.367 -     * readObject and readUnshared from returning additional references to the
   1.368 -     * deserialized instance obtained via this call.  Specifically:
   1.369 -     * <ul>
   1.370 -     *   <li>If readUnshared is called to deserialize a back-reference (the
   1.371 -     *       stream representation of an object which has been written
   1.372 -     *       previously to the stream), an ObjectStreamException will be
   1.373 -     *       thrown.
   1.374 -     *
   1.375 -     *   <li>If readUnshared returns successfully, then any subsequent attempts
   1.376 -     *       to deserialize back-references to the stream handle deserialized
   1.377 -     *       by readUnshared will cause an ObjectStreamException to be thrown.
   1.378 -     * </ul>
   1.379 -     * Deserializing an object via readUnshared invalidates the stream handle
   1.380 -     * associated with the returned object.  Note that this in itself does not
   1.381 -     * always guarantee that the reference returned by readUnshared is unique;
   1.382 -     * the deserialized object may define a readResolve method which returns an
   1.383 -     * object visible to other parties, or readUnshared may return a Class
   1.384 -     * object or enum constant obtainable elsewhere in the stream or through
   1.385 -     * external means. If the deserialized object defines a readResolve method
   1.386 -     * and the invocation of that method returns an array, then readUnshared
   1.387 -     * returns a shallow clone of that array; this guarantees that the returned
   1.388 -     * array object is unique and cannot be obtained a second time from an
   1.389 -     * invocation of readObject or readUnshared on the ObjectInputStream,
   1.390 -     * even if the underlying data stream has been manipulated.
   1.391 -     *
   1.392 -     * <p>ObjectInputStream subclasses which override this method can only be
   1.393 -     * constructed in security contexts possessing the
   1.394 -     * "enableSubclassImplementation" SerializablePermission; any attempt to
   1.395 -     * instantiate such a subclass without this permission will cause a
   1.396 -     * SecurityException to be thrown.
   1.397 -     *
   1.398 -     * @return  reference to deserialized object
   1.399 -     * @throws  ClassNotFoundException if class of an object to deserialize
   1.400 -     *          cannot be found
   1.401 -     * @throws  StreamCorruptedException if control information in the stream
   1.402 -     *          is inconsistent
   1.403 -     * @throws  ObjectStreamException if object to deserialize has already
   1.404 -     *          appeared in stream
   1.405 -     * @throws  OptionalDataException if primitive data is next in stream
   1.406 -     * @throws  IOException if an I/O error occurs during deserialization
   1.407 -     * @since   1.4
   1.408 -     */
   1.409 -    public Object readUnshared() throws IOException, ClassNotFoundException {
   1.410 -        // if nested read, passHandle contains handle of enclosing object
   1.411 -        int outerHandle = passHandle;
   1.412 -        try {
   1.413 -            Object obj = readObject0(true);
   1.414 -            handles.markDependency(outerHandle, passHandle);
   1.415 -            ClassNotFoundException ex = handles.lookupException(passHandle);
   1.416 -            if (ex != null) {
   1.417 -                throw ex;
   1.418 -            }
   1.419 -            if (depth == 0) {
   1.420 -                vlist.doCallbacks();
   1.421 -            }
   1.422 -            return obj;
   1.423 -        } finally {
   1.424 -            passHandle = outerHandle;
   1.425 -            if (closed && depth == 0) {
   1.426 -                clear();
   1.427 -            }
   1.428 -        }
   1.429 -    }
   1.430 -
   1.431 -    /**
   1.432 -     * Read the non-static and non-transient fields of the current class from
   1.433 -     * this stream.  This may only be called from the readObject method of the
   1.434 -     * class being deserialized. It will throw the NotActiveException if it is
   1.435 -     * called otherwise.
   1.436 -     *
   1.437 -     * @throws  ClassNotFoundException if the class of a serialized object
   1.438 -     *          could not be found.
   1.439 -     * @throws  IOException if an I/O error occurs.
   1.440 -     * @throws  NotActiveException if the stream is not currently reading
   1.441 -     *          objects.
   1.442 -     */
   1.443 -    public void defaultReadObject()
   1.444 -        throws IOException, ClassNotFoundException
   1.445 -    {
   1.446 -        if (curContext == null) {
   1.447 -            throw new NotActiveException("not in call to readObject");
   1.448 -        }
   1.449 -        Object curObj = null; // curContext.getObj();
   1.450 -        ObjectStreamClass curDesc = null; // curContext.getDesc();
   1.451 -        bin.setBlockDataMode(false);
   1.452 -        defaultReadFields(curObj, curDesc);
   1.453 -        bin.setBlockDataMode(true);
   1.454 -        if (!curDesc.hasWriteObjectData()) {
   1.455 -            /*
   1.456 -             * Fix for 4360508: since stream does not contain terminating
   1.457 -             * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
   1.458 -             * knows to simulate end-of-custom-data behavior.
   1.459 -             */
   1.460 -            defaultDataEnd = true;
   1.461 -        }
   1.462 -        ClassNotFoundException ex = handles.lookupException(passHandle);
   1.463 -        if (ex != null) {
   1.464 -            throw ex;
   1.465 -        }
   1.466 -    }
   1.467 -
   1.468 -    /**
   1.469 -     * Reads the persistent fields from the stream and makes them available by
   1.470 -     * name.
   1.471 -     *
   1.472 -     * @return  the <code>GetField</code> object representing the persistent
   1.473 -     *          fields of the object being deserialized
   1.474 -     * @throws  ClassNotFoundException if the class of a serialized object
   1.475 -     *          could not be found.
   1.476 -     * @throws  IOException if an I/O error occurs.
   1.477 -     * @throws  NotActiveException if the stream is not currently reading
   1.478 -     *          objects.
   1.479 -     * @since 1.2
   1.480 -     */
   1.481 -    public ObjectInputStream.GetField readFields()
   1.482 -        throws IOException, ClassNotFoundException
   1.483 -    {
   1.484 -        if (curContext == null) {
   1.485 -            throw new NotActiveException("not in call to readObject");
   1.486 -        }
   1.487 -        Object curObj = null; // curContext.getObj();
   1.488 -        ObjectStreamClass curDesc = null; // curContext.getDesc();
   1.489 -        bin.setBlockDataMode(false);
   1.490 -        GetFieldImpl getField = new GetFieldImpl(curDesc);
   1.491 -        getField.readFields();
   1.492 -        bin.setBlockDataMode(true);
   1.493 -        if (!curDesc.hasWriteObjectData()) {
   1.494 -            /*
   1.495 -             * Fix for 4360508: since stream does not contain terminating
   1.496 -             * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
   1.497 -             * knows to simulate end-of-custom-data behavior.
   1.498 -             */
   1.499 -            defaultDataEnd = true;
   1.500 -        }
   1.501 -
   1.502 -        return getField;
   1.503 -    }
   1.504 -
   1.505 -    /**
   1.506 -     * Register an object to be validated before the graph is returned.  While
   1.507 -     * similar to resolveObject these validations are called after the entire
   1.508 -     * graph has been reconstituted.  Typically, a readObject method will
   1.509 -     * register the object with the stream so that when all of the objects are
   1.510 -     * restored a final set of validations can be performed.
   1.511 -     *
   1.512 -     * @param   obj the object to receive the validation callback.
   1.513 -     * @param   prio controls the order of callbacks;zero is a good default.
   1.514 -     *          Use higher numbers to be called back earlier, lower numbers for
   1.515 -     *          later callbacks. Within a priority, callbacks are processed in
   1.516 -     *          no particular order.
   1.517 -     * @throws  NotActiveException The stream is not currently reading objects
   1.518 -     *          so it is invalid to register a callback.
   1.519 -     * @throws  InvalidObjectException The validation object is null.
   1.520 -     */
   1.521 -    public void registerValidation(ObjectInputValidation obj, int prio)
   1.522 -        throws NotActiveException, InvalidObjectException
   1.523 -    {
   1.524 -        if (depth == 0) {
   1.525 -            throw new NotActiveException("stream inactive");
   1.526 -        }
   1.527 -        vlist.register(obj, prio);
   1.528 -    }
   1.529 -
   1.530 -    /**
   1.531 -     * Load the local class equivalent of the specified stream class
   1.532 -     * description.  Subclasses may implement this method to allow classes to
   1.533 -     * be fetched from an alternate source.
   1.534 -     *
   1.535 -     * <p>The corresponding method in <code>ObjectOutputStream</code> is
   1.536 -     * <code>annotateClass</code>.  This method will be invoked only once for
   1.537 -     * each unique class in the stream.  This method can be implemented by
   1.538 -     * subclasses to use an alternate loading mechanism but must return a
   1.539 -     * <code>Class</code> object. Once returned, if the class is not an array
   1.540 -     * class, its serialVersionUID is compared to the serialVersionUID of the
   1.541 -     * serialized class, and if there is a mismatch, the deserialization fails
   1.542 -     * and an {@link InvalidClassException} is thrown.
   1.543 -     *
   1.544 -     * <p>The default implementation of this method in
   1.545 -     * <code>ObjectInputStream</code> returns the result of calling
   1.546 -     * <pre>
   1.547 -     *     Class.forName(desc.getName(), false, loader)
   1.548 -     * </pre>
   1.549 -     * where <code>loader</code> is determined as follows: if there is a
   1.550 -     * method on the current thread's stack whose declaring class was
   1.551 -     * defined by a user-defined class loader (and was not a generated to
   1.552 -     * implement reflective invocations), then <code>loader</code> is class
   1.553 -     * loader corresponding to the closest such method to the currently
   1.554 -     * executing frame; otherwise, <code>loader</code> is
   1.555 -     * <code>null</code>. If this call results in a
   1.556 -     * <code>ClassNotFoundException</code> and the name of the passed
   1.557 -     * <code>ObjectStreamClass</code> instance is the Java language keyword
   1.558 -     * for a primitive type or void, then the <code>Class</code> object
   1.559 -     * representing that primitive type or void will be returned
   1.560 -     * (e.g., an <code>ObjectStreamClass</code> with the name
   1.561 -     * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
   1.562 -     * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
   1.563 -     * the caller of this method.
   1.564 -     *
   1.565 -     * @param   desc an instance of class <code>ObjectStreamClass</code>
   1.566 -     * @return  a <code>Class</code> object corresponding to <code>desc</code>
   1.567 -     * @throws  IOException any of the usual Input/Output exceptions.
   1.568 -     * @throws  ClassNotFoundException if class of a serialized object cannot
   1.569 -     *          be found.
   1.570 -     */
   1.571 -    protected Class<?> resolveClass(ObjectStreamClass desc)
   1.572 -        throws IOException, ClassNotFoundException
   1.573 -    {
   1.574 -        String name = desc.getName();
   1.575 -        try {
   1.576 -            return Class.forName(name, false, latestUserDefinedLoader());
   1.577 -        } catch (ClassNotFoundException ex) {
   1.578 -            Class<?> cl = primClasses.get(name);
   1.579 -            if (cl != null) {
   1.580 -                return cl;
   1.581 -            } else {
   1.582 -                throw ex;
   1.583 -            }
   1.584 -        }
   1.585 -    }
   1.586 -
   1.587 -    /**
   1.588 -     * Returns a proxy class that implements the interfaces named in a proxy
   1.589 -     * class descriptor; subclasses may implement this method to read custom
   1.590 -     * data from the stream along with the descriptors for dynamic proxy
   1.591 -     * classes, allowing them to use an alternate loading mechanism for the
   1.592 -     * interfaces and the proxy class.
   1.593 -     *
   1.594 -     * <p>This method is called exactly once for each unique proxy class
   1.595 -     * descriptor in the stream.
   1.596 -     *
   1.597 -     * <p>The corresponding method in <code>ObjectOutputStream</code> is
   1.598 -     * <code>annotateProxyClass</code>.  For a given subclass of
   1.599 -     * <code>ObjectInputStream</code> that overrides this method, the
   1.600 -     * <code>annotateProxyClass</code> method in the corresponding subclass of
   1.601 -     * <code>ObjectOutputStream</code> must write any data or objects read by
   1.602 -     * this method.
   1.603 -     *
   1.604 -     * <p>The default implementation of this method in
   1.605 -     * <code>ObjectInputStream</code> returns the result of calling
   1.606 -     * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
   1.607 -     * objects for the interfaces that are named in the <code>interfaces</code>
   1.608 -     * parameter.  The <code>Class</code> object for each interface name
   1.609 -     * <code>i</code> is the value returned by calling
   1.610 -     * <pre>
   1.611 -     *     Class.forName(i, false, loader)
   1.612 -     * </pre>
   1.613 -     * where <code>loader</code> is that of the first non-<code>null</code>
   1.614 -     * class loader up the execution stack, or <code>null</code> if no
   1.615 -     * non-<code>null</code> class loaders are on the stack (the same class
   1.616 -     * loader choice used by the <code>resolveClass</code> method).  Unless any
   1.617 -     * of the resolved interfaces are non-public, this same value of
   1.618 -     * <code>loader</code> is also the class loader passed to
   1.619 -     * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
   1.620 -     * their class loader is passed instead (if more than one non-public
   1.621 -     * interface class loader is encountered, an
   1.622 -     * <code>IllegalAccessError</code> is thrown).
   1.623 -     * If <code>Proxy.getProxyClass</code> throws an
   1.624 -     * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
   1.625 -     * will throw a <code>ClassNotFoundException</code> containing the
   1.626 -     * <code>IllegalArgumentException</code>.
   1.627 -     *
   1.628 -     * @param interfaces the list of interface names that were
   1.629 -     *                deserialized in the proxy class descriptor
   1.630 -     * @return  a proxy class for the specified interfaces
   1.631 -     * @throws        IOException any exception thrown by the underlying
   1.632 -     *                <code>InputStream</code>
   1.633 -     * @throws        ClassNotFoundException if the proxy class or any of the
   1.634 -     *                named interfaces could not be found
   1.635 -     * @see ObjectOutputStream#annotateProxyClass(Class)
   1.636 -     * @since 1.3
   1.637 -     */
   1.638 -    protected Class<?> resolveProxyClass(String[] interfaces)
   1.639 -        throws IOException, ClassNotFoundException
   1.640 -    {
   1.641 -        ClassLoader latestLoader = latestUserDefinedLoader();
   1.642 -        ClassLoader nonPublicLoader = null;
   1.643 -        boolean hasNonPublicInterface = false;
   1.644 -
   1.645 -        // define proxy in class loader of non-public interface(s), if any
   1.646 -        Class[] classObjs = new Class[interfaces.length];
   1.647 -        for (int i = 0; i < interfaces.length; i++) {
   1.648 -            Class cl = Class.forName(interfaces[i], false, latestLoader);
   1.649 -            if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
   1.650 -                if (hasNonPublicInterface) {
   1.651 -                    if (nonPublicLoader != cl.getClassLoader()) {
   1.652 -                        throw new IllegalAccessError(
   1.653 -                            "conflicting non-public interface class loaders");
   1.654 -                    }
   1.655 -                } else {
   1.656 -                    nonPublicLoader = cl.getClassLoader();
   1.657 -                    hasNonPublicInterface = true;
   1.658 -                }
   1.659 -            }
   1.660 -            classObjs[i] = cl;
   1.661 -        }
   1.662 -        try {
   1.663 -            return Proxy.getProxyClass(
   1.664 -                hasNonPublicInterface ? nonPublicLoader : latestLoader,
   1.665 -                classObjs);
   1.666 -        } catch (IllegalArgumentException e) {
   1.667 -            throw new ClassNotFoundException(null, e);
   1.668 -        }
   1.669 -    }
   1.670 -
   1.671 -    /**
   1.672 -     * This method will allow trusted subclasses of ObjectInputStream to
   1.673 -     * substitute one object for another during deserialization. Replacing
   1.674 -     * objects is disabled until enableResolveObject is called. The
   1.675 -     * enableResolveObject method checks that the stream requesting to resolve
   1.676 -     * object can be trusted. Every reference to serializable objects is passed
   1.677 -     * to resolveObject.  To insure that the private state of objects is not
   1.678 -     * unintentionally exposed only trusted streams may use resolveObject.
   1.679 -     *
   1.680 -     * <p>This method is called after an object has been read but before it is
   1.681 -     * returned from readObject.  The default resolveObject method just returns
   1.682 -     * the same object.
   1.683 -     *
   1.684 -     * <p>When a subclass is replacing objects it must insure that the
   1.685 -     * substituted object is compatible with every field where the reference
   1.686 -     * will be stored.  Objects whose type is not a subclass of the type of the
   1.687 -     * field or array element abort the serialization by raising an exception
   1.688 -     * and the object is not be stored.
   1.689 -     *
   1.690 -     * <p>This method is called only once when each object is first
   1.691 -     * encountered.  All subsequent references to the object will be redirected
   1.692 -     * to the new object.
   1.693 -     *
   1.694 -     * @param   obj object to be substituted
   1.695 -     * @return  the substituted object
   1.696 -     * @throws  IOException Any of the usual Input/Output exceptions.
   1.697 -     */
   1.698 -    protected Object resolveObject(Object obj) throws IOException {
   1.699 -        return obj;
   1.700 -    }
   1.701 -
   1.702 -    /**
   1.703 -     * Enable the stream to allow objects read from the stream to be replaced.
   1.704 -     * When enabled, the resolveObject method is called for every object being
   1.705 -     * deserialized.
   1.706 -     *
   1.707 -     * <p>If <i>enable</i> is true, and there is a security manager installed,
   1.708 -     * this method first calls the security manager's
   1.709 -     * <code>checkPermission</code> method with the
   1.710 -     * <code>SerializablePermission("enableSubstitution")</code> permission to
   1.711 -     * ensure it's ok to enable the stream to allow objects read from the
   1.712 -     * stream to be replaced.
   1.713 -     *
   1.714 -     * @param   enable true for enabling use of <code>resolveObject</code> for
   1.715 -     *          every object being deserialized
   1.716 -     * @return  the previous setting before this method was invoked
   1.717 -     * @throws  SecurityException if a security manager exists and its
   1.718 -     *          <code>checkPermission</code> method denies enabling the stream
   1.719 -     *          to allow objects read from the stream to be replaced.
   1.720 -     * @see SecurityManager#checkPermission
   1.721 -     * @see java.io.SerializablePermission
   1.722 -     */
   1.723 -    protected boolean enableResolveObject(boolean enable)
   1.724 -        throws SecurityException
   1.725 -    {
   1.726 -        throw new SecurityException();
   1.727 -    }
   1.728 -
   1.729 -    /**
   1.730 -     * The readStreamHeader method is provided to allow subclasses to read and
   1.731 -     * verify their own stream headers. It reads and verifies the magic number
   1.732 -     * and version number.
   1.733 -     *
   1.734 -     * @throws  IOException if there are I/O errors while reading from the
   1.735 -     *          underlying <code>InputStream</code>
   1.736 -     * @throws  StreamCorruptedException if control information in the stream
   1.737 -     *          is inconsistent
   1.738 -     */
   1.739 -    protected void readStreamHeader()
   1.740 -        throws IOException, StreamCorruptedException
   1.741 -    {
   1.742 -        short s0 = bin.readShort();
   1.743 -        short s1 = bin.readShort();
   1.744 -        if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
   1.745 -            throw new StreamCorruptedException(
   1.746 -                String.format("invalid stream header: %04X%04X", s0, s1));
   1.747 -        }
   1.748 -    }
   1.749 -
   1.750 -    /**
   1.751 -     * Read a class descriptor from the serialization stream.  This method is
   1.752 -     * called when the ObjectInputStream expects a class descriptor as the next
   1.753 -     * item in the serialization stream.  Subclasses of ObjectInputStream may
   1.754 -     * override this method to read in class descriptors that have been written
   1.755 -     * in non-standard formats (by subclasses of ObjectOutputStream which have
   1.756 -     * overridden the <code>writeClassDescriptor</code> method).  By default,
   1.757 -     * this method reads class descriptors according to the format defined in
   1.758 -     * the Object Serialization specification.
   1.759 -     *
   1.760 -     * @return  the class descriptor read
   1.761 -     * @throws  IOException If an I/O error has occurred.
   1.762 -     * @throws  ClassNotFoundException If the Class of a serialized object used
   1.763 -     *          in the class descriptor representation cannot be found
   1.764 -     * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
   1.765 -     * @since 1.3
   1.766 -     */
   1.767 -    protected ObjectStreamClass readClassDescriptor()
   1.768 -        throws IOException, ClassNotFoundException
   1.769 -    {
   1.770 -        ObjectStreamClass desc = new ObjectStreamClass();
   1.771 -        desc.readNonProxy(this);
   1.772 -        return desc;
   1.773 -    }
   1.774 -
   1.775 -    /**
   1.776 -     * Reads a byte of data. This method will block if no input is available.
   1.777 -     *
   1.778 -     * @return  the byte read, or -1 if the end of the stream is reached.
   1.779 -     * @throws  IOException If an I/O error has occurred.
   1.780 -     */
   1.781 -    public int read() throws IOException {
   1.782 -        return bin.read();
   1.783 -    }
   1.784 -
   1.785 -    /**
   1.786 -     * Reads into an array of bytes.  This method will block until some input
   1.787 -     * is available. Consider using java.io.DataInputStream.readFully to read
   1.788 -     * exactly 'length' bytes.
   1.789 -     *
   1.790 -     * @param   buf the buffer into which the data is read
   1.791 -     * @param   off the start offset of the data
   1.792 -     * @param   len the maximum number of bytes read
   1.793 -     * @return  the actual number of bytes read, -1 is returned when the end of
   1.794 -     *          the stream is reached.
   1.795 -     * @throws  IOException If an I/O error has occurred.
   1.796 -     * @see java.io.DataInputStream#readFully(byte[],int,int)
   1.797 -     */
   1.798 -    public int read(byte[] buf, int off, int len) throws IOException {
   1.799 -        if (buf == null) {
   1.800 -            throw new NullPointerException();
   1.801 -        }
   1.802 -        int endoff = off + len;
   1.803 -        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
   1.804 -            throw new IndexOutOfBoundsException();
   1.805 -        }
   1.806 -        return bin.read(buf, off, len, false);
   1.807 -    }
   1.808 -
   1.809 -    /**
   1.810 -     * Returns the number of bytes that can be read without blocking.
   1.811 -     *
   1.812 -     * @return  the number of available bytes.
   1.813 -     * @throws  IOException if there are I/O errors while reading from the
   1.814 -     *          underlying <code>InputStream</code>
   1.815 -     */
   1.816 -    public int available() throws IOException {
   1.817 -        return bin.available();
   1.818 -    }
   1.819 -
   1.820 -    /**
   1.821 -     * Closes the input stream. Must be called to release any resources
   1.822 -     * associated with the stream.
   1.823 -     *
   1.824 -     * @throws  IOException If an I/O error has occurred.
   1.825 -     */
   1.826 -    public void close() throws IOException {
   1.827 -        /*
   1.828 -         * Even if stream already closed, propagate redundant close to
   1.829 -         * underlying stream to stay consistent with previous implementations.
   1.830 -         */
   1.831 -        closed = true;
   1.832 -        if (depth == 0) {
   1.833 -            clear();
   1.834 -        }
   1.835 -        bin.close();
   1.836 -    }
   1.837 -
   1.838 -    /**
   1.839 -     * Reads in a boolean.
   1.840 -     *
   1.841 -     * @return  the boolean read.
   1.842 -     * @throws  EOFException If end of file is reached.
   1.843 -     * @throws  IOException If other I/O error has occurred.
   1.844 -     */
   1.845 -    public boolean readBoolean() throws IOException {
   1.846 -        return bin.readBoolean();
   1.847 -    }
   1.848 -
   1.849 -    /**
   1.850 -     * Reads an 8 bit byte.
   1.851 -     *
   1.852 -     * @return  the 8 bit byte read.
   1.853 -     * @throws  EOFException If end of file is reached.
   1.854 -     * @throws  IOException If other I/O error has occurred.
   1.855 -     */
   1.856 -    public byte readByte() throws IOException  {
   1.857 -        return bin.readByte();
   1.858 -    }
   1.859 -
   1.860 -    /**
   1.861 -     * Reads an unsigned 8 bit byte.
   1.862 -     *
   1.863 -     * @return  the 8 bit byte read.
   1.864 -     * @throws  EOFException If end of file is reached.
   1.865 -     * @throws  IOException If other I/O error has occurred.
   1.866 -     */
   1.867 -    public int readUnsignedByte()  throws IOException {
   1.868 -        return bin.readUnsignedByte();
   1.869 -    }
   1.870 -
   1.871 -    /**
   1.872 -     * Reads a 16 bit char.
   1.873 -     *
   1.874 -     * @return  the 16 bit char read.
   1.875 -     * @throws  EOFException If end of file is reached.
   1.876 -     * @throws  IOException If other I/O error has occurred.
   1.877 -     */
   1.878 -    public char readChar()  throws IOException {
   1.879 -        return bin.readChar();
   1.880 -    }
   1.881 -
   1.882 -    /**
   1.883 -     * Reads a 16 bit short.
   1.884 -     *
   1.885 -     * @return  the 16 bit short read.
   1.886 -     * @throws  EOFException If end of file is reached.
   1.887 -     * @throws  IOException If other I/O error has occurred.
   1.888 -     */
   1.889 -    public short readShort()  throws IOException {
   1.890 -        return bin.readShort();
   1.891 -    }
   1.892 -
   1.893 -    /**
   1.894 -     * Reads an unsigned 16 bit short.
   1.895 -     *
   1.896 -     * @return  the 16 bit short read.
   1.897 -     * @throws  EOFException If end of file is reached.
   1.898 -     * @throws  IOException If other I/O error has occurred.
   1.899 -     */
   1.900 -    public int readUnsignedShort() throws IOException {
   1.901 -        return bin.readUnsignedShort();
   1.902 -    }
   1.903 -
   1.904 -    /**
   1.905 -     * Reads a 32 bit int.
   1.906 -     *
   1.907 -     * @return  the 32 bit integer read.
   1.908 -     * @throws  EOFException If end of file is reached.
   1.909 -     * @throws  IOException If other I/O error has occurred.
   1.910 -     */
   1.911 -    public int readInt()  throws IOException {
   1.912 -        return bin.readInt();
   1.913 -    }
   1.914 -
   1.915 -    /**
   1.916 -     * Reads a 64 bit long.
   1.917 -     *
   1.918 -     * @return  the read 64 bit long.
   1.919 -     * @throws  EOFException If end of file is reached.
   1.920 -     * @throws  IOException If other I/O error has occurred.
   1.921 -     */
   1.922 -    public long readLong()  throws IOException {
   1.923 -        return bin.readLong();
   1.924 -    }
   1.925 -
   1.926 -    /**
   1.927 -     * Reads a 32 bit float.
   1.928 -     *
   1.929 -     * @return  the 32 bit float read.
   1.930 -     * @throws  EOFException If end of file is reached.
   1.931 -     * @throws  IOException If other I/O error has occurred.
   1.932 -     */
   1.933 -    public float readFloat() throws IOException {
   1.934 -        return bin.readFloat();
   1.935 -    }
   1.936 -
   1.937 -    /**
   1.938 -     * Reads a 64 bit double.
   1.939 -     *
   1.940 -     * @return  the 64 bit double read.
   1.941 -     * @throws  EOFException If end of file is reached.
   1.942 -     * @throws  IOException If other I/O error has occurred.
   1.943 -     */
   1.944 -    public double readDouble() throws IOException {
   1.945 -        return bin.readDouble();
   1.946 -    }
   1.947 -
   1.948 -    /**
   1.949 -     * Reads bytes, blocking until all bytes are read.
   1.950 -     *
   1.951 -     * @param   buf the buffer into which the data is read
   1.952 -     * @throws  EOFException If end of file is reached.
   1.953 -     * @throws  IOException If other I/O error has occurred.
   1.954 -     */
   1.955 -    public void readFully(byte[] buf) throws IOException {
   1.956 -        bin.readFully(buf, 0, buf.length, false);
   1.957 -    }
   1.958 -
   1.959 -    /**
   1.960 -     * Reads bytes, blocking until all bytes are read.
   1.961 -     *
   1.962 -     * @param   buf the buffer into which the data is read
   1.963 -     * @param   off the start offset of the data
   1.964 -     * @param   len the maximum number of bytes to read
   1.965 -     * @throws  EOFException If end of file is reached.
   1.966 -     * @throws  IOException If other I/O error has occurred.
   1.967 -     */
   1.968 -    public void readFully(byte[] buf, int off, int len) throws IOException {
   1.969 -        int endoff = off + len;
   1.970 -        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
   1.971 -            throw new IndexOutOfBoundsException();
   1.972 -        }
   1.973 -        bin.readFully(buf, off, len, false);
   1.974 -    }
   1.975 -
   1.976 -    /**
   1.977 -     * Skips bytes.
   1.978 -     *
   1.979 -     * @param   len the number of bytes to be skipped
   1.980 -     * @return  the actual number of bytes skipped.
   1.981 -     * @throws  IOException If an I/O error has occurred.
   1.982 -     */
   1.983 -    public int skipBytes(int len) throws IOException {
   1.984 -        return bin.skipBytes(len);
   1.985 -    }
   1.986 -
   1.987 -    /**
   1.988 -     * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
   1.989 -     *
   1.990 -     * @return  a String copy of the line.
   1.991 -     * @throws  IOException if there are I/O errors while reading from the
   1.992 -     *          underlying <code>InputStream</code>
   1.993 -     * @deprecated This method does not properly convert bytes to characters.
   1.994 -     *          see DataInputStream for the details and alternatives.
   1.995 -     */
   1.996 -    @Deprecated
   1.997 -    public String readLine() throws IOException {
   1.998 -        return bin.readLine();
   1.999 -    }
  1.1000 -
  1.1001 -    /**
  1.1002 -     * Reads a String in
  1.1003 -     * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
  1.1004 -     * format.
  1.1005 -     *
  1.1006 -     * @return  the String.
  1.1007 -     * @throws  IOException if there are I/O errors while reading from the
  1.1008 -     *          underlying <code>InputStream</code>
  1.1009 -     * @throws  UTFDataFormatException if read bytes do not represent a valid
  1.1010 -     *          modified UTF-8 encoding of a string
  1.1011 -     */
  1.1012 -    public String readUTF() throws IOException {
  1.1013 -        return bin.readUTF();
  1.1014 -    }
  1.1015 -
  1.1016 -    /**
  1.1017 -     * Provide access to the persistent fields read from the input stream.
  1.1018 -     */
  1.1019 -    public static abstract class GetField {
  1.1020 -
  1.1021 -        /**
  1.1022 -         * Get the ObjectStreamClass that describes the fields in the stream.
  1.1023 -         *
  1.1024 -         * @return  the descriptor class that describes the serializable fields
  1.1025 -         */
  1.1026 -        public abstract ObjectStreamClass getObjectStreamClass();
  1.1027 -
  1.1028 -        /**
  1.1029 -         * Return true if the named field is defaulted and has no value in this
  1.1030 -         * stream.
  1.1031 -         *
  1.1032 -         * @param  name the name of the field
  1.1033 -         * @return true, if and only if the named field is defaulted
  1.1034 -         * @throws IOException if there are I/O errors while reading from
  1.1035 -         *         the underlying <code>InputStream</code>
  1.1036 -         * @throws IllegalArgumentException if <code>name</code> does not
  1.1037 -         *         correspond to a serializable field
  1.1038 -         */
  1.1039 -        public abstract boolean defaulted(String name) throws IOException;
  1.1040 -
  1.1041 -        /**
  1.1042 -         * Get the value of the named boolean field from the persistent field.
  1.1043 -         *
  1.1044 -         * @param  name the name of the field
  1.1045 -         * @param  val the default value to use if <code>name</code> does not
  1.1046 -         *         have a value
  1.1047 -         * @return the value of the named <code>boolean</code> field
  1.1048 -         * @throws IOException if there are I/O errors while reading from the
  1.1049 -         *         underlying <code>InputStream</code>
  1.1050 -         * @throws IllegalArgumentException if type of <code>name</code> is
  1.1051 -         *         not serializable or if the field type is incorrect
  1.1052 -         */
  1.1053 -        public abstract boolean get(String name, boolean val)
  1.1054 -            throws IOException;
  1.1055 -
  1.1056 -        /**
  1.1057 -         * Get the value of the named byte field from the persistent field.
  1.1058 -         *
  1.1059 -         * @param  name the name of the field
  1.1060 -         * @param  val the default value to use if <code>name</code> does not
  1.1061 -         *         have a value
  1.1062 -         * @return the value of the named <code>byte</code> field
  1.1063 -         * @throws IOException if there are I/O errors while reading from the
  1.1064 -         *         underlying <code>InputStream</code>
  1.1065 -         * @throws IllegalArgumentException if type of <code>name</code> is
  1.1066 -         *         not serializable or if the field type is incorrect
  1.1067 -         */
  1.1068 -        public abstract byte get(String name, byte val) throws IOException;
  1.1069 -
  1.1070 -        /**
  1.1071 -         * Get the value of the named char field from the persistent field.
  1.1072 -         *
  1.1073 -         * @param  name the name of the field
  1.1074 -         * @param  val the default value to use if <code>name</code> does not
  1.1075 -         *         have a value
  1.1076 -         * @return the value of the named <code>char</code> field
  1.1077 -         * @throws IOException if there are I/O errors while reading from the
  1.1078 -         *         underlying <code>InputStream</code>
  1.1079 -         * @throws IllegalArgumentException if type of <code>name</code> is
  1.1080 -         *         not serializable or if the field type is incorrect
  1.1081 -         */
  1.1082 -        public abstract char get(String name, char val) throws IOException;
  1.1083 -
  1.1084 -        /**
  1.1085 -         * Get the value of the named short field from the persistent field.
  1.1086 -         *
  1.1087 -         * @param  name the name of the field
  1.1088 -         * @param  val the default value to use if <code>name</code> does not
  1.1089 -         *         have a value
  1.1090 -         * @return the value of the named <code>short</code> field
  1.1091 -         * @throws IOException if there are I/O errors while reading from the
  1.1092 -         *         underlying <code>InputStream</code>
  1.1093 -         * @throws IllegalArgumentException if type of <code>name</code> is
  1.1094 -         *         not serializable or if the field type is incorrect
  1.1095 -         */
  1.1096 -        public abstract short get(String name, short val) throws IOException;
  1.1097 -
  1.1098 -        /**
  1.1099 -         * Get the value of the named int field from the persistent field.
  1.1100 -         *
  1.1101 -         * @param  name the name of the field
  1.1102 -         * @param  val the default value to use if <code>name</code> does not
  1.1103 -         *         have a value
  1.1104 -         * @return the value of the named <code>int</code> field
  1.1105 -         * @throws IOException if there are I/O errors while reading from the
  1.1106 -         *         underlying <code>InputStream</code>
  1.1107 -         * @throws IllegalArgumentException if type of <code>name</code> is
  1.1108 -         *         not serializable or if the field type is incorrect
  1.1109 -         */
  1.1110 -        public abstract int get(String name, int val) throws IOException;
  1.1111 -
  1.1112 -        /**
  1.1113 -         * Get the value of the named long field from the persistent field.
  1.1114 -         *
  1.1115 -         * @param  name the name of the field
  1.1116 -         * @param  val the default value to use if <code>name</code> does not
  1.1117 -         *         have a value
  1.1118 -         * @return the value of the named <code>long</code> field
  1.1119 -         * @throws IOException if there are I/O errors while reading from the
  1.1120 -         *         underlying <code>InputStream</code>
  1.1121 -         * @throws IllegalArgumentException if type of <code>name</code> is
  1.1122 -         *         not serializable or if the field type is incorrect
  1.1123 -         */
  1.1124 -        public abstract long get(String name, long val) throws IOException;
  1.1125 -
  1.1126 -        /**
  1.1127 -         * Get the value of the named float field from the persistent field.
  1.1128 -         *
  1.1129 -         * @param  name the name of the field
  1.1130 -         * @param  val the default value to use if <code>name</code> does not
  1.1131 -         *         have a value
  1.1132 -         * @return the value of the named <code>float</code> field
  1.1133 -         * @throws IOException if there are I/O errors while reading from the
  1.1134 -         *         underlying <code>InputStream</code>
  1.1135 -         * @throws IllegalArgumentException if type of <code>name</code> is
  1.1136 -         *         not serializable or if the field type is incorrect
  1.1137 -         */
  1.1138 -        public abstract float get(String name, float val) throws IOException;
  1.1139 -
  1.1140 -        /**
  1.1141 -         * Get the value of the named double field from the persistent field.
  1.1142 -         *
  1.1143 -         * @param  name the name of the field
  1.1144 -         * @param  val the default value to use if <code>name</code> does not
  1.1145 -         *         have a value
  1.1146 -         * @return the value of the named <code>double</code> field
  1.1147 -         * @throws IOException if there are I/O errors while reading from the
  1.1148 -         *         underlying <code>InputStream</code>
  1.1149 -         * @throws IllegalArgumentException if type of <code>name</code> is
  1.1150 -         *         not serializable or if the field type is incorrect
  1.1151 -         */
  1.1152 -        public abstract double get(String name, double val) throws IOException;
  1.1153 -
  1.1154 -        /**
  1.1155 -         * Get the value of the named Object field from the persistent field.
  1.1156 -         *
  1.1157 -         * @param  name the name of the field
  1.1158 -         * @param  val the default value to use if <code>name</code> does not
  1.1159 -         *         have a value
  1.1160 -         * @return the value of the named <code>Object</code> field
  1.1161 -         * @throws IOException if there are I/O errors while reading from the
  1.1162 -         *         underlying <code>InputStream</code>
  1.1163 -         * @throws IllegalArgumentException if type of <code>name</code> is
  1.1164 -         *         not serializable or if the field type is incorrect
  1.1165 -         */
  1.1166 -        public abstract Object get(String name, Object val) throws IOException;
  1.1167 -    }
  1.1168 -
  1.1169 -    /**
  1.1170 -     * Verifies that this (possibly subclass) instance can be constructed
  1.1171 -     * without violating security constraints: the subclass must not override
  1.1172 -     * security-sensitive non-final methods, or else the
  1.1173 -     * "enableSubclassImplementation" SerializablePermission is checked.
  1.1174 -     */
  1.1175 -    private void verifySubclass() {
  1.1176 -        Class cl = getClass();
  1.1177 -        if (cl == ObjectInputStream.class) {
  1.1178 -            return;
  1.1179 -        }
  1.1180 -        throw new SecurityException();
  1.1181 -    }
  1.1182 -
  1.1183 -    /**
  1.1184 -     * Clears internal data structures.
  1.1185 -     */
  1.1186 -    private void clear() {
  1.1187 -        handles.clear();
  1.1188 -        vlist.clear();
  1.1189 -    }
  1.1190 -
  1.1191 -    /**
  1.1192 -     * Underlying readObject implementation.
  1.1193 -     */
  1.1194 -    private Object readObject0(boolean unshared) throws IOException {
  1.1195 -        boolean oldMode = bin.getBlockDataMode();
  1.1196 -        if (oldMode) {
  1.1197 -            int remain = bin.currentBlockRemaining();
  1.1198 -            if (remain > 0) {
  1.1199 -                throw new OptionalDataException(remain);
  1.1200 -            } else if (defaultDataEnd) {
  1.1201 -                /*
  1.1202 -                 * Fix for 4360508: stream is currently at the end of a field
  1.1203 -                 * value block written via default serialization; since there
  1.1204 -                 * is no terminating TC_ENDBLOCKDATA tag, simulate
  1.1205 -                 * end-of-custom-data behavior explicitly.
  1.1206 -                 */
  1.1207 -                throw new OptionalDataException(true);
  1.1208 -            }
  1.1209 -            bin.setBlockDataMode(false);
  1.1210 -        }
  1.1211 -
  1.1212 -        byte tc;
  1.1213 -        while ((tc = bin.peekByte()) == TC_RESET) {
  1.1214 -            bin.readByte();
  1.1215 -            handleReset();
  1.1216 -        }
  1.1217 -
  1.1218 -        depth++;
  1.1219 -        try {
  1.1220 -            switch (tc) {
  1.1221 -                case TC_NULL:
  1.1222 -                    return readNull();
  1.1223 -
  1.1224 -                case TC_REFERENCE:
  1.1225 -                    return readHandle(unshared);
  1.1226 -
  1.1227 -                case TC_CLASS:
  1.1228 -                    return readClass(unshared);
  1.1229 -
  1.1230 -                case TC_CLASSDESC:
  1.1231 -                case TC_PROXYCLASSDESC:
  1.1232 -                    return readClassDesc(unshared);
  1.1233 -
  1.1234 -                case TC_STRING:
  1.1235 -                case TC_LONGSTRING:
  1.1236 -                    return checkResolve(readString(unshared));
  1.1237 -
  1.1238 -                case TC_ARRAY:
  1.1239 -                    return checkResolve(readArray(unshared));
  1.1240 -
  1.1241 -                case TC_ENUM:
  1.1242 -                    return checkResolve(readEnum(unshared));
  1.1243 -
  1.1244 -                case TC_OBJECT:
  1.1245 -                    return checkResolve(readOrdinaryObject(unshared));
  1.1246 -
  1.1247 -                case TC_EXCEPTION:
  1.1248 -                    IOException ex = readFatalException();
  1.1249 -                    throw new WriteAbortedException("writing aborted", ex);
  1.1250 -
  1.1251 -                case TC_BLOCKDATA:
  1.1252 -                case TC_BLOCKDATALONG:
  1.1253 -                    if (oldMode) {
  1.1254 -                        bin.setBlockDataMode(true);
  1.1255 -                        bin.peek();             // force header read
  1.1256 -                        throw new OptionalDataException(
  1.1257 -                            bin.currentBlockRemaining());
  1.1258 -                    } else {
  1.1259 -                        throw new StreamCorruptedException(
  1.1260 -                            "unexpected block data");
  1.1261 -                    }
  1.1262 -
  1.1263 -                case TC_ENDBLOCKDATA:
  1.1264 -                    if (oldMode) {
  1.1265 -                        throw new OptionalDataException(true);
  1.1266 -                    } else {
  1.1267 -                        throw new StreamCorruptedException(
  1.1268 -                            "unexpected end of block data");
  1.1269 -                    }
  1.1270 -
  1.1271 -                default:
  1.1272 -                    throw new StreamCorruptedException(
  1.1273 -                        String.format("invalid type code: %02X", tc));
  1.1274 -            }
  1.1275 -        } finally {
  1.1276 -            depth--;
  1.1277 -            bin.setBlockDataMode(oldMode);
  1.1278 -        }
  1.1279 -    }
  1.1280 -
  1.1281 -    /**
  1.1282 -     * If resolveObject has been enabled and given object does not have an
  1.1283 -     * exception associated with it, calls resolveObject to determine
  1.1284 -     * replacement for object, and updates handle table accordingly.  Returns
  1.1285 -     * replacement object, or echoes provided object if no replacement
  1.1286 -     * occurred.  Expects that passHandle is set to given object's handle prior
  1.1287 -     * to calling this method.
  1.1288 -     */
  1.1289 -    private Object checkResolve(Object obj) throws IOException {
  1.1290 -        if (!enableResolve || handles.lookupException(passHandle) != null) {
  1.1291 -            return obj;
  1.1292 -        }
  1.1293 -        Object rep = resolveObject(obj);
  1.1294 -        if (rep != obj) {
  1.1295 -            handles.setObject(passHandle, rep);
  1.1296 -        }
  1.1297 -        return rep;
  1.1298 -    }
  1.1299 -
  1.1300 -    /**
  1.1301 -     * Reads string without allowing it to be replaced in stream.  Called from
  1.1302 -     * within ObjectStreamClass.read().
  1.1303 -     */
  1.1304 -    String readTypeString() throws IOException {
  1.1305 -        int oldHandle = passHandle;
  1.1306 -        try {
  1.1307 -            byte tc = bin.peekByte();
  1.1308 -            switch (tc) {
  1.1309 -                case TC_NULL:
  1.1310 -                    return (String) readNull();
  1.1311 -
  1.1312 -                case TC_REFERENCE:
  1.1313 -                    return (String) readHandle(false);
  1.1314 -
  1.1315 -                case TC_STRING:
  1.1316 -                case TC_LONGSTRING:
  1.1317 -                    return readString(false);
  1.1318 -
  1.1319 -                default:
  1.1320 -                    throw new StreamCorruptedException(
  1.1321 -                        String.format("invalid type code: %02X", tc));
  1.1322 -            }
  1.1323 -        } finally {
  1.1324 -            passHandle = oldHandle;
  1.1325 -        }
  1.1326 -    }
  1.1327 -
  1.1328 -    /**
  1.1329 -     * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
  1.1330 -     */
  1.1331 -    private Object readNull() throws IOException {
  1.1332 -        if (bin.readByte() != TC_NULL) {
  1.1333 -            throw new InternalError();
  1.1334 -        }
  1.1335 -        passHandle = NULL_HANDLE;
  1.1336 -        return null;
  1.1337 -    }
  1.1338 -
  1.1339 -    /**
  1.1340 -     * Reads in object handle, sets passHandle to the read handle, and returns
  1.1341 -     * object associated with the handle.
  1.1342 -     */
  1.1343 -    private Object readHandle(boolean unshared) throws IOException {
  1.1344 -        if (bin.readByte() != TC_REFERENCE) {
  1.1345 -            throw new InternalError();
  1.1346 -        }
  1.1347 -        passHandle = bin.readInt() - baseWireHandle;
  1.1348 -        if (passHandle < 0 || passHandle >= handles.size()) {
  1.1349 -            throw new StreamCorruptedException(
  1.1350 -                String.format("invalid handle value: %08X", passHandle +
  1.1351 -                baseWireHandle));
  1.1352 -        }
  1.1353 -        if (unshared) {
  1.1354 -            // REMIND: what type of exception to throw here?
  1.1355 -            throw new InvalidObjectException(
  1.1356 -                "cannot read back reference as unshared");
  1.1357 -        }
  1.1358 -
  1.1359 -        Object obj = handles.lookupObject(passHandle);
  1.1360 -        if (obj == unsharedMarker) {
  1.1361 -            // REMIND: what type of exception to throw here?
  1.1362 -            throw new InvalidObjectException(
  1.1363 -                "cannot read back reference to unshared object");
  1.1364 -        }
  1.1365 -        return obj;
  1.1366 -    }
  1.1367 -
  1.1368 -    /**
  1.1369 -     * Reads in and returns class object.  Sets passHandle to class object's
  1.1370 -     * assigned handle.  Returns null if class is unresolvable (in which case a
  1.1371 -     * ClassNotFoundException will be associated with the class' handle in the
  1.1372 -     * handle table).
  1.1373 -     */
  1.1374 -    private Class readClass(boolean unshared) throws IOException {
  1.1375 -        if (bin.readByte() != TC_CLASS) {
  1.1376 -            throw new InternalError();
  1.1377 -        }
  1.1378 -        ObjectStreamClass desc = readClassDesc(false);
  1.1379 -        Class cl = desc.forClass();
  1.1380 -        passHandle = handles.assign(unshared ? unsharedMarker : cl);
  1.1381 -
  1.1382 -        ClassNotFoundException resolveEx = desc.getResolveException();
  1.1383 -        if (resolveEx != null) {
  1.1384 -            handles.markException(passHandle, resolveEx);
  1.1385 -        }
  1.1386 -
  1.1387 -        handles.finish(passHandle);
  1.1388 -        return cl;
  1.1389 -    }
  1.1390 -
  1.1391 -    /**
  1.1392 -     * Reads in and returns (possibly null) class descriptor.  Sets passHandle
  1.1393 -     * to class descriptor's assigned handle.  If class descriptor cannot be
  1.1394 -     * resolved to a class in the local VM, a ClassNotFoundException is
  1.1395 -     * associated with the class descriptor's handle.
  1.1396 -     */
  1.1397 -    private ObjectStreamClass readClassDesc(boolean unshared)
  1.1398 -        throws IOException
  1.1399 -    {
  1.1400 -        byte tc = bin.peekByte();
  1.1401 -        switch (tc) {
  1.1402 -            case TC_NULL:
  1.1403 -                return (ObjectStreamClass) readNull();
  1.1404 -
  1.1405 -            case TC_REFERENCE:
  1.1406 -                return (ObjectStreamClass) readHandle(unshared);
  1.1407 -
  1.1408 -            case TC_PROXYCLASSDESC:
  1.1409 -                return readProxyDesc(unshared);
  1.1410 -
  1.1411 -            case TC_CLASSDESC:
  1.1412 -                return readNonProxyDesc(unshared);
  1.1413 -
  1.1414 -            default:
  1.1415 -                throw new StreamCorruptedException(
  1.1416 -                    String.format("invalid type code: %02X", tc));
  1.1417 -        }
  1.1418 -    }
  1.1419 -
  1.1420 -    /**
  1.1421 -     * Reads in and returns class descriptor for a dynamic proxy class.  Sets
  1.1422 -     * passHandle to proxy class descriptor's assigned handle.  If proxy class
  1.1423 -     * descriptor cannot be resolved to a class in the local VM, a
  1.1424 -     * ClassNotFoundException is associated with the descriptor's handle.
  1.1425 -     */
  1.1426 -    private ObjectStreamClass readProxyDesc(boolean unshared)
  1.1427 -        throws IOException
  1.1428 -    {
  1.1429 -        if (bin.readByte() != TC_PROXYCLASSDESC) {
  1.1430 -            throw new InternalError();
  1.1431 -        }
  1.1432 -
  1.1433 -        ObjectStreamClass desc = new ObjectStreamClass();
  1.1434 -        int descHandle = handles.assign(unshared ? unsharedMarker : desc);
  1.1435 -        passHandle = NULL_HANDLE;
  1.1436 -
  1.1437 -        int numIfaces = bin.readInt();
  1.1438 -        String[] ifaces = new String[numIfaces];
  1.1439 -        for (int i = 0; i < numIfaces; i++) {
  1.1440 -            ifaces[i] = bin.readUTF();
  1.1441 -        }
  1.1442 -
  1.1443 -        Class cl = null;
  1.1444 -        ClassNotFoundException resolveEx = null;
  1.1445 -        bin.setBlockDataMode(true);
  1.1446 -        try {
  1.1447 -            if ((cl = resolveProxyClass(ifaces)) == null) {
  1.1448 -                resolveEx = new ClassNotFoundException("null class");
  1.1449 -            }
  1.1450 -        } catch (ClassNotFoundException ex) {
  1.1451 -            resolveEx = ex;
  1.1452 -        }
  1.1453 -        skipCustomData();
  1.1454 -
  1.1455 -        desc.initProxy(cl, resolveEx, readClassDesc(false));
  1.1456 -
  1.1457 -        handles.finish(descHandle);
  1.1458 -        passHandle = descHandle;
  1.1459 -        return desc;
  1.1460 -    }
  1.1461 -
  1.1462 -    /**
  1.1463 -     * Reads in and returns class descriptor for a class that is not a dynamic
  1.1464 -     * proxy class.  Sets passHandle to class descriptor's assigned handle.  If
  1.1465 -     * class descriptor cannot be resolved to a class in the local VM, a
  1.1466 -     * ClassNotFoundException is associated with the descriptor's handle.
  1.1467 -     */
  1.1468 -    private ObjectStreamClass readNonProxyDesc(boolean unshared)
  1.1469 -        throws IOException
  1.1470 -    {
  1.1471 -        if (bin.readByte() != TC_CLASSDESC) {
  1.1472 -            throw new InternalError();
  1.1473 -        }
  1.1474 -
  1.1475 -        ObjectStreamClass desc = new ObjectStreamClass();
  1.1476 -        int descHandle = handles.assign(unshared ? unsharedMarker : desc);
  1.1477 -        passHandle = NULL_HANDLE;
  1.1478 -
  1.1479 -        ObjectStreamClass readDesc = null;
  1.1480 -        try {
  1.1481 -            readDesc = readClassDescriptor();
  1.1482 -        } catch (ClassNotFoundException ex) {
  1.1483 -            throw (IOException) new InvalidClassException(
  1.1484 -                "failed to read class descriptor").initCause(ex);
  1.1485 -        }
  1.1486 -
  1.1487 -        Class cl = null;
  1.1488 -        ClassNotFoundException resolveEx = null;
  1.1489 -        bin.setBlockDataMode(true);
  1.1490 -        try {
  1.1491 -            if ((cl = resolveClass(readDesc)) == null) {
  1.1492 -                resolveEx = new ClassNotFoundException("null class");
  1.1493 -            }
  1.1494 -        } catch (ClassNotFoundException ex) {
  1.1495 -            resolveEx = ex;
  1.1496 -        }
  1.1497 -        skipCustomData();
  1.1498 -
  1.1499 -        desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
  1.1500 -
  1.1501 -        handles.finish(descHandle);
  1.1502 -        passHandle = descHandle;
  1.1503 -        return desc;
  1.1504 -    }
  1.1505 -
  1.1506 -    /**
  1.1507 -     * Reads in and returns new string.  Sets passHandle to new string's
  1.1508 -     * assigned handle.
  1.1509 -     */
  1.1510 -    private String readString(boolean unshared) throws IOException {
  1.1511 -        String str;
  1.1512 -        byte tc = bin.readByte();
  1.1513 -        switch (tc) {
  1.1514 -            case TC_STRING:
  1.1515 -                str = bin.readUTF();
  1.1516 -                break;
  1.1517 -
  1.1518 -            case TC_LONGSTRING:
  1.1519 -                str = bin.readLongUTF();
  1.1520 -                break;
  1.1521 -
  1.1522 -            default:
  1.1523 -                throw new StreamCorruptedException(
  1.1524 -                    String.format("invalid type code: %02X", tc));
  1.1525 -        }
  1.1526 -        passHandle = handles.assign(unshared ? unsharedMarker : str);
  1.1527 -        handles.finish(passHandle);
  1.1528 -        return str;
  1.1529 -    }
  1.1530 -
  1.1531 -    /**
  1.1532 -     * Reads in and returns array object, or null if array class is
  1.1533 -     * unresolvable.  Sets passHandle to array's assigned handle.
  1.1534 -     */
  1.1535 -    private Object readArray(boolean unshared) throws IOException {
  1.1536 -        if (bin.readByte() != TC_ARRAY) {
  1.1537 -            throw new InternalError();
  1.1538 -        }
  1.1539 -
  1.1540 -        ObjectStreamClass desc = readClassDesc(false);
  1.1541 -        int len = bin.readInt();
  1.1542 -
  1.1543 -        Object array = null;
  1.1544 -        Class cl, ccl = null;
  1.1545 -        if ((cl = desc.forClass()) != null) {
  1.1546 -            ccl = cl.getComponentType();
  1.1547 -            array = Array.newInstance(ccl, len);
  1.1548 -        }
  1.1549 -
  1.1550 -        int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
  1.1551 -        ClassNotFoundException resolveEx = desc.getResolveException();
  1.1552 -        if (resolveEx != null) {
  1.1553 -            handles.markException(arrayHandle, resolveEx);
  1.1554 -        }
  1.1555 -
  1.1556 -        if (ccl == null) {
  1.1557 -            for (int i = 0; i < len; i++) {
  1.1558 -                readObject0(false);
  1.1559 -            }
  1.1560 -        } else if (ccl.isPrimitive()) {
  1.1561 -            if (ccl == Integer.TYPE) {
  1.1562 -                bin.readInts((int[]) array, 0, len);
  1.1563 -            } else if (ccl == Byte.TYPE) {
  1.1564 -                bin.readFully((byte[]) array, 0, len, true);
  1.1565 -            } else if (ccl == Long.TYPE) {
  1.1566 -                bin.readLongs((long[]) array, 0, len);
  1.1567 -            } else if (ccl == Float.TYPE) {
  1.1568 -                bin.readFloats((float[]) array, 0, len);
  1.1569 -            } else if (ccl == Double.TYPE) {
  1.1570 -                bin.readDoubles((double[]) array, 0, len);
  1.1571 -            } else if (ccl == Short.TYPE) {
  1.1572 -                bin.readShorts((short[]) array, 0, len);
  1.1573 -            } else if (ccl == Character.TYPE) {
  1.1574 -                bin.readChars((char[]) array, 0, len);
  1.1575 -            } else if (ccl == Boolean.TYPE) {
  1.1576 -                bin.readBooleans((boolean[]) array, 0, len);
  1.1577 -            } else {
  1.1578 -                throw new InternalError();
  1.1579 -            }
  1.1580 -        } else {
  1.1581 -            Object[] oa = (Object[]) array;
  1.1582 -            for (int i = 0; i < len; i++) {
  1.1583 -                oa[i] = readObject0(false);
  1.1584 -                handles.markDependency(arrayHandle, passHandle);
  1.1585 -            }
  1.1586 -        }
  1.1587 -
  1.1588 -        handles.finish(arrayHandle);
  1.1589 -        passHandle = arrayHandle;
  1.1590 -        return array;
  1.1591 -    }
  1.1592 -
  1.1593 -    /**
  1.1594 -     * Reads in and returns enum constant, or null if enum type is
  1.1595 -     * unresolvable.  Sets passHandle to enum constant's assigned handle.
  1.1596 -     */
  1.1597 -    private Enum readEnum(boolean unshared) throws IOException {
  1.1598 -        if (bin.readByte() != TC_ENUM) {
  1.1599 -            throw new InternalError();
  1.1600 -        }
  1.1601 -
  1.1602 -        ObjectStreamClass desc = readClassDesc(false);
  1.1603 -        if (!desc.isEnum()) {
  1.1604 -            throw new InvalidClassException("non-enum class: " + desc);
  1.1605 -        }
  1.1606 -
  1.1607 -        int enumHandle = handles.assign(unshared ? unsharedMarker : null);
  1.1608 -        ClassNotFoundException resolveEx = desc.getResolveException();
  1.1609 -        if (resolveEx != null) {
  1.1610 -            handles.markException(enumHandle, resolveEx);
  1.1611 -        }
  1.1612 -
  1.1613 -        String name = readString(false);
  1.1614 -        Enum en = null;
  1.1615 -        Class cl = desc.forClass();
  1.1616 -        if (cl != null) {
  1.1617 -            try {
  1.1618 -                en = Enum.valueOf(cl, name);
  1.1619 -            } catch (IllegalArgumentException ex) {
  1.1620 -                throw (IOException) new InvalidObjectException(
  1.1621 -                    "enum constant " + name + " does not exist in " +
  1.1622 -                    cl).initCause(ex);
  1.1623 -            }
  1.1624 -            if (!unshared) {
  1.1625 -                handles.setObject(enumHandle, en);
  1.1626 -            }
  1.1627 -        }
  1.1628 -
  1.1629 -        handles.finish(enumHandle);
  1.1630 -        passHandle = enumHandle;
  1.1631 -        return en;
  1.1632 -    }
  1.1633 -
  1.1634 -    /**
  1.1635 -     * Reads and returns "ordinary" (i.e., not a String, Class,
  1.1636 -     * ObjectStreamClass, array, or enum constant) object, or null if object's
  1.1637 -     * class is unresolvable (in which case a ClassNotFoundException will be
  1.1638 -     * associated with object's handle).  Sets passHandle to object's assigned
  1.1639 -     * handle.
  1.1640 -     */
  1.1641 -    private Object readOrdinaryObject(boolean unshared)
  1.1642 -        throws IOException
  1.1643 -    {
  1.1644 -        if (bin.readByte() != TC_OBJECT) {
  1.1645 -            throw new InternalError();
  1.1646 -        }
  1.1647 -
  1.1648 -        ObjectStreamClass desc = readClassDesc(false);
  1.1649 -        desc.checkDeserialize();
  1.1650 -
  1.1651 -        Object obj;
  1.1652 -        try {
  1.1653 -            obj = desc.isInstantiable() ? desc.newInstance() : null;
  1.1654 -        } catch (Exception ex) {
  1.1655 -            throw (IOException) new InvalidClassException(
  1.1656 -                desc.forClass().getName(),
  1.1657 -                "unable to create instance").initCause(ex);
  1.1658 -        }
  1.1659 -
  1.1660 -        passHandle = handles.assign(unshared ? unsharedMarker : obj);
  1.1661 -        ClassNotFoundException resolveEx = desc.getResolveException();
  1.1662 -        if (resolveEx != null) {
  1.1663 -            handles.markException(passHandle, resolveEx);
  1.1664 -        }
  1.1665 -
  1.1666 -        if (desc.isExternalizable()) {
  1.1667 -            readExternalData((Externalizable) obj, desc);
  1.1668 -        } else {
  1.1669 -            readSerialData(obj, desc);
  1.1670 -        }
  1.1671 -
  1.1672 -        handles.finish(passHandle);
  1.1673 -
  1.1674 -        if (obj != null &&
  1.1675 -            handles.lookupException(passHandle) == null &&
  1.1676 -            desc.hasReadResolveMethod())
  1.1677 -        {
  1.1678 -            Object rep = desc.invokeReadResolve(obj);
  1.1679 -            if (unshared && rep.getClass().isArray()) {
  1.1680 -                rep = cloneArray(rep);
  1.1681 -            }
  1.1682 -            if (rep != obj) {
  1.1683 -                handles.setObject(passHandle, obj = rep);
  1.1684 -            }
  1.1685 -        }
  1.1686 -
  1.1687 -        return obj;
  1.1688 -    }
  1.1689 -
  1.1690 -    /**
  1.1691 -     * If obj is non-null, reads externalizable data by invoking readExternal()
  1.1692 -     * method of obj; otherwise, attempts to skip over externalizable data.
  1.1693 -     * Expects that passHandle is set to obj's handle before this method is
  1.1694 -     * called.
  1.1695 -     */
  1.1696 -    private void readExternalData(Externalizable obj, ObjectStreamClass desc)
  1.1697 -        throws IOException
  1.1698 -    {
  1.1699 -        Object oldContext = curContext;
  1.1700 -        curContext = null;
  1.1701 -        try {
  1.1702 -            boolean blocked = desc.hasBlockExternalData();
  1.1703 -            if (blocked) {
  1.1704 -                bin.setBlockDataMode(true);
  1.1705 -            }
  1.1706 -            if (obj != null) {
  1.1707 -                try {
  1.1708 -                    obj.readExternal(this);
  1.1709 -                } catch (ClassNotFoundException ex) {
  1.1710 -                    /*
  1.1711 -                     * In most cases, the handle table has already propagated
  1.1712 -                     * a CNFException to passHandle at this point; this mark
  1.1713 -                     * call is included to address cases where the readExternal
  1.1714 -                     * method has cons'ed and thrown a new CNFException of its
  1.1715 -                     * own.
  1.1716 -                     */
  1.1717 -                     handles.markException(passHandle, ex);
  1.1718 -                }
  1.1719 -            }
  1.1720 -            if (blocked) {
  1.1721 -                skipCustomData();
  1.1722 -            }
  1.1723 -        } finally {
  1.1724 -            curContext = oldContext;
  1.1725 -        }
  1.1726 -        /*
  1.1727 -         * At this point, if the externalizable data was not written in
  1.1728 -         * block-data form and either the externalizable class doesn't exist
  1.1729 -         * locally (i.e., obj == null) or readExternal() just threw a
  1.1730 -         * CNFException, then the stream is probably in an inconsistent state,
  1.1731 -         * since some (or all) of the externalizable data may not have been
  1.1732 -         * consumed.  Since there's no "correct" action to take in this case,
  1.1733 -         * we mimic the behavior of past serialization implementations and
  1.1734 -         * blindly hope that the stream is in sync; if it isn't and additional
  1.1735 -         * externalizable data remains in the stream, a subsequent read will
  1.1736 -         * most likely throw a StreamCorruptedException.
  1.1737 -         */
  1.1738 -    }
  1.1739 -
  1.1740 -    /**
  1.1741 -     * Reads (or attempts to skip, if obj is null or is tagged with a
  1.1742 -     * ClassNotFoundException) instance data for each serializable class of
  1.1743 -     * object in stream, from superclass to subclass.  Expects that passHandle
  1.1744 -     * is set to obj's handle before this method is called.
  1.1745 -     */
  1.1746 -    private void readSerialData(Object obj, ObjectStreamClass desc)
  1.1747 -        throws IOException
  1.1748 -    {
  1.1749 -        ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
  1.1750 -        for (int i = 0; i < slots.length; i++) {
  1.1751 -            ObjectStreamClass slotDesc = slots[i].desc;
  1.1752 -
  1.1753 -            if (slots[i].hasData) {
  1.1754 -                if (obj != null &&
  1.1755 -                    slotDesc.hasReadObjectMethod() &&
  1.1756 -                    handles.lookupException(passHandle) == null)
  1.1757 -                {
  1.1758 -                    Object oldContext = curContext;
  1.1759 -
  1.1760 -                    try {
  1.1761 -                        curContext = null; //new SerialCallbackContext(obj, slotDesc);
  1.1762 -
  1.1763 -                        bin.setBlockDataMode(true);
  1.1764 -                        slotDesc.invokeReadObject(obj, this);
  1.1765 -                    } catch (ClassNotFoundException ex) {
  1.1766 -                        /*
  1.1767 -                         * In most cases, the handle table has already
  1.1768 -                         * propagated a CNFException to passHandle at this
  1.1769 -                         * point; this mark call is included to address cases
  1.1770 -                         * where the custom readObject method has cons'ed and
  1.1771 -                         * thrown a new CNFException of its own.
  1.1772 -                         */
  1.1773 -                        handles.markException(passHandle, ex);
  1.1774 -                    } finally {
  1.1775 -                        //curContext.setUsed();
  1.1776 -                        curContext = oldContext;
  1.1777 -                    }
  1.1778 -
  1.1779 -                    /*
  1.1780 -                     * defaultDataEnd may have been set indirectly by custom
  1.1781 -                     * readObject() method when calling defaultReadObject() or
  1.1782 -                     * readFields(); clear it to restore normal read behavior.
  1.1783 -                     */
  1.1784 -                    defaultDataEnd = false;
  1.1785 -                } else {
  1.1786 -                    defaultReadFields(obj, slotDesc);
  1.1787 -                }
  1.1788 -                if (slotDesc.hasWriteObjectData()) {
  1.1789 -                    skipCustomData();
  1.1790 -                } else {
  1.1791 -                    bin.setBlockDataMode(false);
  1.1792 -                }
  1.1793 -            } else {
  1.1794 -                if (obj != null &&
  1.1795 -                    slotDesc.hasReadObjectNoDataMethod() &&
  1.1796 -                    handles.lookupException(passHandle) == null)
  1.1797 -                {
  1.1798 -                    slotDesc.invokeReadObjectNoData(obj);
  1.1799 -                }
  1.1800 -            }
  1.1801 -        }
  1.1802 -    }
  1.1803 -
  1.1804 -    /**
  1.1805 -     * Skips over all block data and objects until TC_ENDBLOCKDATA is
  1.1806 -     * encountered.
  1.1807 -     */
  1.1808 -    private void skipCustomData() throws IOException {
  1.1809 -        int oldHandle = passHandle;
  1.1810 -        for (;;) {
  1.1811 -            if (bin.getBlockDataMode()) {
  1.1812 -                bin.skipBlockData();
  1.1813 -                bin.setBlockDataMode(false);
  1.1814 -            }
  1.1815 -            switch (bin.peekByte()) {
  1.1816 -                case TC_BLOCKDATA:
  1.1817 -                case TC_BLOCKDATALONG:
  1.1818 -                    bin.setBlockDataMode(true);
  1.1819 -                    break;
  1.1820 -
  1.1821 -                case TC_ENDBLOCKDATA:
  1.1822 -                    bin.readByte();
  1.1823 -                    passHandle = oldHandle;
  1.1824 -                    return;
  1.1825 -
  1.1826 -                default:
  1.1827 -                    readObject0(false);
  1.1828 -                    break;
  1.1829 -            }
  1.1830 -        }
  1.1831 -    }
  1.1832 -
  1.1833 -    /**
  1.1834 -     * Reads in values of serializable fields declared by given class
  1.1835 -     * descriptor.  If obj is non-null, sets field values in obj.  Expects that
  1.1836 -     * passHandle is set to obj's handle before this method is called.
  1.1837 -     */
  1.1838 -    private void defaultReadFields(Object obj, ObjectStreamClass desc)
  1.1839 -        throws IOException
  1.1840 -    {
  1.1841 -        // REMIND: is isInstance check necessary?
  1.1842 -        Class cl = desc.forClass();
  1.1843 -        if (cl != null && obj != null && !cl.isInstance(obj)) {
  1.1844 -            throw new ClassCastException();
  1.1845 -        }
  1.1846 -
  1.1847 -        int primDataSize = desc.getPrimDataSize();
  1.1848 -        if (primVals == null || primVals.length < primDataSize) {
  1.1849 -            primVals = new byte[primDataSize];
  1.1850 -        }
  1.1851 -        bin.readFully(primVals, 0, primDataSize, false);
  1.1852 -        if (obj != null) {
  1.1853 -            desc.setPrimFieldValues(obj, primVals);
  1.1854 -        }
  1.1855 -
  1.1856 -        int objHandle = passHandle;
  1.1857 -        ObjectStreamField[] fields = desc.getFields(false);
  1.1858 -        Object[] objVals = new Object[desc.getNumObjFields()];
  1.1859 -        int numPrimFields = fields.length - objVals.length;
  1.1860 -        for (int i = 0; i < objVals.length; i++) {
  1.1861 -            ObjectStreamField f = fields[numPrimFields + i];
  1.1862 -            objVals[i] = readObject0(f.isUnshared());
  1.1863 -            if (f.getField() != null) {
  1.1864 -                handles.markDependency(objHandle, passHandle);
  1.1865 -            }
  1.1866 -        }
  1.1867 -        if (obj != null) {
  1.1868 -            desc.setObjFieldValues(obj, objVals);
  1.1869 -        }
  1.1870 -        passHandle = objHandle;
  1.1871 -    }
  1.1872 -
  1.1873 -    /**
  1.1874 -     * Reads in and returns IOException that caused serialization to abort.
  1.1875 -     * All stream state is discarded prior to reading in fatal exception.  Sets
  1.1876 -     * passHandle to fatal exception's handle.
  1.1877 -     */
  1.1878 -    private IOException readFatalException() throws IOException {
  1.1879 -        if (bin.readByte() != TC_EXCEPTION) {
  1.1880 -            throw new InternalError();
  1.1881 -        }
  1.1882 -        clear();
  1.1883 -        return (IOException) readObject0(false);
  1.1884 -    }
  1.1885 -
  1.1886 -    /**
  1.1887 -     * If recursion depth is 0, clears internal data structures; otherwise,
  1.1888 -     * throws a StreamCorruptedException.  This method is called when a
  1.1889 -     * TC_RESET typecode is encountered.
  1.1890 -     */
  1.1891 -    private void handleReset() throws StreamCorruptedException {
  1.1892 -        if (depth > 0) {
  1.1893 -            throw new StreamCorruptedException(
  1.1894 -                "unexpected reset; recursion depth: " + depth);
  1.1895 -        }
  1.1896 -        clear();
  1.1897 -    }
  1.1898 -
  1.1899 -    /**
  1.1900 -     * Converts specified span of bytes into float values.
  1.1901 -     */
  1.1902 -    // REMIND: remove once hotspot inlines Float.intBitsToFloat
  1.1903 -    private static native void bytesToFloats(byte[] src, int srcpos,
  1.1904 -                                             float[] dst, int dstpos,
  1.1905 -                                             int nfloats);
  1.1906 -
  1.1907 -    /**
  1.1908 -     * Converts specified span of bytes into double values.
  1.1909 -     */
  1.1910 -    // REMIND: remove once hotspot inlines Double.longBitsToDouble
  1.1911 -    private static native void bytesToDoubles(byte[] src, int srcpos,
  1.1912 -                                              double[] dst, int dstpos,
  1.1913 -                                              int ndoubles);
  1.1914 -
  1.1915 -    /**
  1.1916 -     * Returns the first non-null class loader (not counting class loaders of
  1.1917 -     * generated reflection implementation classes) up the execution stack, or
  1.1918 -     * null if only code from the null class loader is on the stack.  This
  1.1919 -     * method is also called via reflection by the following RMI-IIOP class:
  1.1920 -     *
  1.1921 -     *     com.sun.corba.se.internal.util.JDKClassLoader
  1.1922 -     *
  1.1923 -     * This method should not be removed or its signature changed without
  1.1924 -     * corresponding modifications to the above class.
  1.1925 -     */
  1.1926 -    // REMIND: change name to something more accurate?
  1.1927 -    private static native ClassLoader latestUserDefinedLoader();
  1.1928 -
  1.1929 -    /**
  1.1930 -     * Default GetField implementation.
  1.1931 -     */
  1.1932 -    private class GetFieldImpl extends GetField {
  1.1933 -
  1.1934 -        /** class descriptor describing serializable fields */
  1.1935 -        private final ObjectStreamClass desc;
  1.1936 -        /** primitive field values */
  1.1937 -        private final byte[] primVals;
  1.1938 -        /** object field values */
  1.1939 -        private final Object[] objVals;
  1.1940 -        /** object field value handles */
  1.1941 -        private final int[] objHandles;
  1.1942 -
  1.1943 -        /**
  1.1944 -         * Creates GetFieldImpl object for reading fields defined in given
  1.1945 -         * class descriptor.
  1.1946 -         */
  1.1947 -        GetFieldImpl(ObjectStreamClass desc) {
  1.1948 -            this.desc = desc;
  1.1949 -            primVals = new byte[desc.getPrimDataSize()];
  1.1950 -            objVals = new Object[desc.getNumObjFields()];
  1.1951 -            objHandles = new int[objVals.length];
  1.1952 -        }
  1.1953 -
  1.1954 -        public ObjectStreamClass getObjectStreamClass() {
  1.1955 -            return desc;
  1.1956 -        }
  1.1957 -
  1.1958 -        public boolean defaulted(String name) throws IOException {
  1.1959 -            return (getFieldOffset(name, null) < 0);
  1.1960 -        }
  1.1961 -
  1.1962 -        public boolean get(String name, boolean val) throws IOException {
  1.1963 -            int off = getFieldOffset(name, Boolean.TYPE);
  1.1964 -            return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
  1.1965 -        }
  1.1966 -
  1.1967 -        public byte get(String name, byte val) throws IOException {
  1.1968 -            int off = getFieldOffset(name, Byte.TYPE);
  1.1969 -            return (off >= 0) ? primVals[off] : val;
  1.1970 -        }
  1.1971 -
  1.1972 -        public char get(String name, char val) throws IOException {
  1.1973 -            int off = getFieldOffset(name, Character.TYPE);
  1.1974 -            return (off >= 0) ? Bits.getChar(primVals, off) : val;
  1.1975 -        }
  1.1976 -
  1.1977 -        public short get(String name, short val) throws IOException {
  1.1978 -            int off = getFieldOffset(name, Short.TYPE);
  1.1979 -            return (off >= 0) ? Bits.getShort(primVals, off) : val;
  1.1980 -        }
  1.1981 -
  1.1982 -        public int get(String name, int val) throws IOException {
  1.1983 -            int off = getFieldOffset(name, Integer.TYPE);
  1.1984 -            return (off >= 0) ? Bits.getInt(primVals, off) : val;
  1.1985 -        }
  1.1986 -
  1.1987 -        public float get(String name, float val) throws IOException {
  1.1988 -            int off = getFieldOffset(name, Float.TYPE);
  1.1989 -            return (off >= 0) ? Bits.getFloat(primVals, off) : val;
  1.1990 -        }
  1.1991 -
  1.1992 -        public long get(String name, long val) throws IOException {
  1.1993 -            int off = getFieldOffset(name, Long.TYPE);
  1.1994 -            return (off >= 0) ? Bits.getLong(primVals, off) : val;
  1.1995 -        }
  1.1996 -
  1.1997 -        public double get(String name, double val) throws IOException {
  1.1998 -            int off = getFieldOffset(name, Double.TYPE);
  1.1999 -            return (off >= 0) ? Bits.getDouble(primVals, off) : val;
  1.2000 -        }
  1.2001 -
  1.2002 -        public Object get(String name, Object val) throws IOException {
  1.2003 -            int off = getFieldOffset(name, Object.class);
  1.2004 -            if (off >= 0) {
  1.2005 -                int objHandle = objHandles[off];
  1.2006 -                handles.markDependency(passHandle, objHandle);
  1.2007 -                return (handles.lookupException(objHandle) == null) ?
  1.2008 -                    objVals[off] : null;
  1.2009 -            } else {
  1.2010 -                return val;
  1.2011 -            }
  1.2012 -        }
  1.2013 -
  1.2014 -        /**
  1.2015 -         * Reads primitive and object field values from stream.
  1.2016 -         */
  1.2017 -        void readFields() throws IOException {
  1.2018 -            bin.readFully(primVals, 0, primVals.length, false);
  1.2019 -
  1.2020 -            int oldHandle = passHandle;
  1.2021 -            ObjectStreamField[] fields = desc.getFields(false);
  1.2022 -            int numPrimFields = fields.length - objVals.length;
  1.2023 -            for (int i = 0; i < objVals.length; i++) {
  1.2024 -                objVals[i] =
  1.2025 -                    readObject0(fields[numPrimFields + i].isUnshared());
  1.2026 -                objHandles[i] = passHandle;
  1.2027 -            }
  1.2028 -            passHandle = oldHandle;
  1.2029 -        }
  1.2030 -
  1.2031 -        /**
  1.2032 -         * Returns offset of field with given name and type.  A specified type
  1.2033 -         * of null matches all types, Object.class matches all non-primitive
  1.2034 -         * types, and any other non-null type matches assignable types only.
  1.2035 -         * If no matching field is found in the (incoming) class
  1.2036 -         * descriptor but a matching field is present in the associated local
  1.2037 -         * class descriptor, returns -1.  Throws IllegalArgumentException if
  1.2038 -         * neither incoming nor local class descriptor contains a match.
  1.2039 -         */
  1.2040 -        private int getFieldOffset(String name, Class type) {
  1.2041 -            ObjectStreamField field = desc.getField(name, type);
  1.2042 -            if (field != null) {
  1.2043 -                return field.getOffset();
  1.2044 -            } else if (desc.getLocalDesc().getField(name, type) != null) {
  1.2045 -                return -1;
  1.2046 -            } else {
  1.2047 -                throw new IllegalArgumentException("no such field " + name +
  1.2048 -                                                   " with type " + type);
  1.2049 -            }
  1.2050 -        }
  1.2051 -    }
  1.2052 -
  1.2053 -    /**
  1.2054 -     * Prioritized list of callbacks to be performed once object graph has been
  1.2055 -     * completely deserialized.
  1.2056 -     */
  1.2057 -    private static class ValidationList {
  1.2058 -
  1.2059 -
  1.2060 -        /**
  1.2061 -         * Creates new (empty) ValidationList.
  1.2062 -         */
  1.2063 -        ValidationList() {
  1.2064 -        }
  1.2065 -
  1.2066 -        /**
  1.2067 -         * Registers callback.  Throws InvalidObjectException if callback
  1.2068 -         * object is null.
  1.2069 -         */
  1.2070 -        void register(ObjectInputValidation obj, int priority)
  1.2071 -            throws InvalidObjectException
  1.2072 -        {
  1.2073 -            if (obj == null) {
  1.2074 -                throw new InvalidObjectException("null callback");
  1.2075 -            }
  1.2076 -            throw new InvalidObjectException("Does not work.");
  1.2077 -        }
  1.2078 -
  1.2079 -        /**
  1.2080 -         * Invokes all registered callbacks and clears the callback list.
  1.2081 -         * Callbacks with higher priorities are called first; those with equal
  1.2082 -         * priorities may be called in any order.  If any of the callbacks
  1.2083 -         * throws an InvalidObjectException, the callback process is terminated
  1.2084 -         * and the exception propagated upwards.
  1.2085 -         */
  1.2086 -        void doCallbacks() throws InvalidObjectException {
  1.2087 -        }
  1.2088 -
  1.2089 -        /**
  1.2090 -         * Resets the callback list to its initial (empty) state.
  1.2091 -         */
  1.2092 -        public void clear() {
  1.2093 -        }
  1.2094 -    }
  1.2095 -
  1.2096 -    /**
  1.2097 -     * Input stream supporting single-byte peek operations.
  1.2098 -     */
  1.2099 -    private static class PeekInputStream extends InputStream {
  1.2100 -
  1.2101 -        /** underlying stream */
  1.2102 -        private final InputStream in;
  1.2103 -        /** peeked byte */
  1.2104 -        private int peekb = -1;
  1.2105 -
  1.2106 -        /**
  1.2107 -         * Creates new PeekInputStream on top of given underlying stream.
  1.2108 -         */
  1.2109 -        PeekInputStream(InputStream in) {
  1.2110 -            this.in = in;
  1.2111 -        }
  1.2112 -
  1.2113 -        /**
  1.2114 -         * Peeks at next byte value in stream.  Similar to read(), except
  1.2115 -         * that it does not consume the read value.
  1.2116 -         */
  1.2117 -        int peek() throws IOException {
  1.2118 -            return (peekb >= 0) ? peekb : (peekb = in.read());
  1.2119 -        }
  1.2120 -
  1.2121 -        public int read() throws IOException {
  1.2122 -            if (peekb >= 0) {
  1.2123 -                int v = peekb;
  1.2124 -                peekb = -1;
  1.2125 -                return v;
  1.2126 -            } else {
  1.2127 -                return in.read();
  1.2128 -            }
  1.2129 -        }
  1.2130 -
  1.2131 -        public int read(byte[] b, int off, int len) throws IOException {
  1.2132 -            if (len == 0) {
  1.2133 -                return 0;
  1.2134 -            } else if (peekb < 0) {
  1.2135 -                return in.read(b, off, len);
  1.2136 -            } else {
  1.2137 -                b[off++] = (byte) peekb;
  1.2138 -                len--;
  1.2139 -                peekb = -1;
  1.2140 -                int n = in.read(b, off, len);
  1.2141 -                return (n >= 0) ? (n + 1) : 1;
  1.2142 -            }
  1.2143 -        }
  1.2144 -
  1.2145 -        void readFully(byte[] b, int off, int len) throws IOException {
  1.2146 -            int n = 0;
  1.2147 -            while (n < len) {
  1.2148 -                int count = read(b, off + n, len - n);
  1.2149 -                if (count < 0) {
  1.2150 -                    throw new EOFException();
  1.2151 -                }
  1.2152 -                n += count;
  1.2153 -            }
  1.2154 -        }
  1.2155 -
  1.2156 -        public long skip(long n) throws IOException {
  1.2157 -            if (n <= 0) {
  1.2158 -                return 0;
  1.2159 -            }
  1.2160 -            int skipped = 0;
  1.2161 -            if (peekb >= 0) {
  1.2162 -                peekb = -1;
  1.2163 -                skipped++;
  1.2164 -                n--;
  1.2165 -            }
  1.2166 -            return skipped + skip(n);
  1.2167 -        }
  1.2168 -
  1.2169 -        public int available() throws IOException {
  1.2170 -            return in.available() + ((peekb >= 0) ? 1 : 0);
  1.2171 -        }
  1.2172 -
  1.2173 -        public void close() throws IOException {
  1.2174 -            in.close();
  1.2175 -        }
  1.2176 -    }
  1.2177 -
  1.2178 -    /**
  1.2179 -     * Input stream with two modes: in default mode, inputs data written in the
  1.2180 -     * same format as DataOutputStream; in "block data" mode, inputs data
  1.2181 -     * bracketed by block data markers (see object serialization specification
  1.2182 -     * for details).  Buffering depends on block data mode: when in default
  1.2183 -     * mode, no data is buffered in advance; when in block data mode, all data
  1.2184 -     * for the current data block is read in at once (and buffered).
  1.2185 -     */
  1.2186 -    private class BlockDataInputStream
  1.2187 -        extends InputStream implements DataInput
  1.2188 -    {
  1.2189 -        /** maximum data block length */
  1.2190 -        private static final int MAX_BLOCK_SIZE = 1024;
  1.2191 -        /** maximum data block header length */
  1.2192 -        private static final int MAX_HEADER_SIZE = 5;
  1.2193 -        /** (tunable) length of char buffer (for reading strings) */
  1.2194 -        private static final int CHAR_BUF_SIZE = 256;
  1.2195 -        /** readBlockHeader() return value indicating header read may block */
  1.2196 -        private static final int HEADER_BLOCKED = -2;
  1.2197 -
  1.2198 -        /** buffer for reading general/block data */
  1.2199 -        private final byte[] buf = new byte[MAX_BLOCK_SIZE];
  1.2200 -        /** buffer for reading block data headers */
  1.2201 -        private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
  1.2202 -        /** char buffer for fast string reads */
  1.2203 -        private final char[] cbuf = new char[CHAR_BUF_SIZE];
  1.2204 -
  1.2205 -        /** block data mode */
  1.2206 -        private boolean blkmode = false;
  1.2207 -
  1.2208 -        // block data state fields; values meaningful only when blkmode true
  1.2209 -        /** current offset into buf */
  1.2210 -        private int pos = 0;
  1.2211 -        /** end offset of valid data in buf, or -1 if no more block data */
  1.2212 -        private int end = -1;
  1.2213 -        /** number of bytes in current block yet to be read from stream */
  1.2214 -        private int unread = 0;
  1.2215 -
  1.2216 -        /** underlying stream (wrapped in peekable filter stream) */
  1.2217 -        private final PeekInputStream in;
  1.2218 -        /** loopback stream (for data reads that span data blocks) */
  1.2219 -        private final DataInputStream din;
  1.2220 -
  1.2221 -        /**
  1.2222 -         * Creates new BlockDataInputStream on top of given underlying stream.
  1.2223 -         * Block data mode is turned off by default.
  1.2224 -         */
  1.2225 -        BlockDataInputStream(InputStream in) {
  1.2226 -            this.in = new PeekInputStream(in);
  1.2227 -            din = new DataInputStream(this);
  1.2228 -        }
  1.2229 -
  1.2230 -        /**
  1.2231 -         * Sets block data mode to the given mode (true == on, false == off)
  1.2232 -         * and returns the previous mode value.  If the new mode is the same as
  1.2233 -         * the old mode, no action is taken.  Throws IllegalStateException if
  1.2234 -         * block data mode is being switched from on to off while unconsumed
  1.2235 -         * block data is still present in the stream.
  1.2236 -         */
  1.2237 -        boolean setBlockDataMode(boolean newmode) throws IOException {
  1.2238 -            if (blkmode == newmode) {
  1.2239 -                return blkmode;
  1.2240 -            }
  1.2241 -            if (newmode) {
  1.2242 -                pos = 0;
  1.2243 -                end = 0;
  1.2244 -                unread = 0;
  1.2245 -            } else if (pos < end) {
  1.2246 -                throw new IllegalStateException("unread block data");
  1.2247 -            }
  1.2248 -            blkmode = newmode;
  1.2249 -            return !blkmode;
  1.2250 -        }
  1.2251 -
  1.2252 -        /**
  1.2253 -         * Returns true if the stream is currently in block data mode, false
  1.2254 -         * otherwise.
  1.2255 -         */
  1.2256 -        boolean getBlockDataMode() {
  1.2257 -            return blkmode;
  1.2258 -        }
  1.2259 -
  1.2260 -        /**
  1.2261 -         * If in block data mode, skips to the end of the current group of data
  1.2262 -         * blocks (but does not unset block data mode).  If not in block data
  1.2263 -         * mode, throws an IllegalStateException.
  1.2264 -         */
  1.2265 -        void skipBlockData() throws IOException {
  1.2266 -            if (!blkmode) {
  1.2267 -                throw new IllegalStateException("not in block data mode");
  1.2268 -            }
  1.2269 -            while (end >= 0) {
  1.2270 -                refill();
  1.2271 -            }
  1.2272 -        }
  1.2273 -
  1.2274 -        /**
  1.2275 -         * Attempts to read in the next block data header (if any).  If
  1.2276 -         * canBlock is false and a full header cannot be read without possibly
  1.2277 -         * blocking, returns HEADER_BLOCKED, else if the next element in the
  1.2278 -         * stream is a block data header, returns the block data length
  1.2279 -         * specified by the header, else returns -1.
  1.2280 -         */
  1.2281 -        private int readBlockHeader(boolean canBlock) throws IOException {
  1.2282 -            if (defaultDataEnd) {
  1.2283 -                /*
  1.2284 -                 * Fix for 4360508: stream is currently at the end of a field
  1.2285 -                 * value block written via default serialization; since there
  1.2286 -                 * is no terminating TC_ENDBLOCKDATA tag, simulate
  1.2287 -                 * end-of-custom-data behavior explicitly.
  1.2288 -                 */
  1.2289 -                return -1;
  1.2290 -            }
  1.2291 -            try {
  1.2292 -                for (;;) {
  1.2293 -                    int avail = canBlock ? Integer.MAX_VALUE : in.available();
  1.2294 -                    if (avail == 0) {
  1.2295 -                        return HEADER_BLOCKED;
  1.2296 -                    }
  1.2297 -
  1.2298 -                    int tc = in.peek();
  1.2299 -                    switch (tc) {
  1.2300 -                        case TC_BLOCKDATA:
  1.2301 -                            if (avail < 2) {
  1.2302 -                                return HEADER_BLOCKED;
  1.2303 -                            }
  1.2304 -                            in.readFully(hbuf, 0, 2);
  1.2305 -                            return hbuf[1] & 0xFF;
  1.2306 -
  1.2307 -                        case TC_BLOCKDATALONG:
  1.2308 -                            if (avail < 5) {
  1.2309 -                                return HEADER_BLOCKED;
  1.2310 -                            }
  1.2311 -                            in.readFully(hbuf, 0, 5);
  1.2312 -                            int len = Bits.getInt(hbuf, 1);
  1.2313 -                            if (len < 0) {
  1.2314 -                                throw new StreamCorruptedException(
  1.2315 -                                    "illegal block data header length: " +
  1.2316 -                                    len);
  1.2317 -                            }
  1.2318 -                            return len;
  1.2319 -
  1.2320 -                        /*
  1.2321 -                         * TC_RESETs may occur in between data blocks.
  1.2322 -                         * Unfortunately, this case must be parsed at a lower
  1.2323 -                         * level than other typecodes, since primitive data
  1.2324 -                         * reads may span data blocks separated by a TC_RESET.
  1.2325 -                         */
  1.2326 -                        case TC_RESET:
  1.2327 -                            in.read();
  1.2328 -                            handleReset();
  1.2329 -                            break;
  1.2330 -
  1.2331 -                        default:
  1.2332 -                            if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
  1.2333 -                                throw new StreamCorruptedException(
  1.2334 -                                    String.format("invalid type code: %02X",
  1.2335 -                                    tc));
  1.2336 -                            }
  1.2337 -                            return -1;
  1.2338 -                    }
  1.2339 -                }
  1.2340 -            } catch (EOFException ex) {
  1.2341 -                throw new StreamCorruptedException(
  1.2342 -                    "unexpected EOF while reading block data header");
  1.2343 -            }
  1.2344 -        }
  1.2345 -
  1.2346 -        /**
  1.2347 -         * Refills internal buffer buf with block data.  Any data in buf at the
  1.2348 -         * time of the call is considered consumed.  Sets the pos, end, and
  1.2349 -         * unread fields to reflect the new amount of available block data; if
  1.2350 -         * the next element in the stream is not a data block, sets pos and
  1.2351 -         * unread to 0 and end to -1.
  1.2352 -         */
  1.2353 -        private void refill() throws IOException {
  1.2354 -            try {
  1.2355 -                do {
  1.2356 -                    pos = 0;
  1.2357 -                    if (unread > 0) {
  1.2358 -                        int n =
  1.2359 -                            in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
  1.2360 -                        if (n >= 0) {
  1.2361 -                            end = n;
  1.2362 -                            unread -= n;
  1.2363 -                        } else {
  1.2364 -                            throw new StreamCorruptedException(
  1.2365 -                                "unexpected EOF in middle of data block");
  1.2366 -                        }
  1.2367 -                    } else {
  1.2368 -                        int n = readBlockHeader(true);
  1.2369 -                        if (n >= 0) {
  1.2370 -                            end = 0;
  1.2371 -                            unread = n;
  1.2372 -                        } else {
  1.2373 -                            end = -1;
  1.2374 -                            unread = 0;
  1.2375 -                        }
  1.2376 -                    }
  1.2377 -                } while (pos == end);
  1.2378 -            } catch (IOException ex) {
  1.2379 -                pos = 0;
  1.2380 -                end = -1;
  1.2381 -                unread = 0;
  1.2382 -                throw ex;
  1.2383 -            }
  1.2384 -        }
  1.2385 -
  1.2386 -        /**
  1.2387 -         * If in block data mode, returns the number of unconsumed bytes
  1.2388 -         * remaining in the current data block.  If not in block data mode,
  1.2389 -         * throws an IllegalStateException.
  1.2390 -         */
  1.2391 -        int currentBlockRemaining() {
  1.2392 -            if (blkmode) {
  1.2393 -                return (end >= 0) ? (end - pos) + unread : 0;
  1.2394 -            } else {
  1.2395 -                throw new IllegalStateException();
  1.2396 -            }
  1.2397 -        }
  1.2398 -
  1.2399 -        /**
  1.2400 -         * Peeks at (but does not consume) and returns the next byte value in
  1.2401 -         * the stream, or -1 if the end of the stream/block data (if in block
  1.2402 -         * data mode) has been reached.
  1.2403 -         */
  1.2404 -        int peek() throws IOException {
  1.2405 -            if (blkmode) {
  1.2406 -                if (pos == end) {
  1.2407 -                    refill();
  1.2408 -                }
  1.2409 -                return (end >= 0) ? (buf[pos] & 0xFF) : -1;
  1.2410 -            } else {
  1.2411 -                return in.peek();
  1.2412 -            }
  1.2413 -        }
  1.2414 -
  1.2415 -        /**
  1.2416 -         * Peeks at (but does not consume) and returns the next byte value in
  1.2417 -         * the stream, or throws EOFException if end of stream/block data has
  1.2418 -         * been reached.
  1.2419 -         */
  1.2420 -        byte peekByte() throws IOException {
  1.2421 -            int val = peek();
  1.2422 -            if (val < 0) {
  1.2423 -                throw new EOFException();
  1.2424 -            }
  1.2425 -            return (byte) val;
  1.2426 -        }
  1.2427 -
  1.2428 -
  1.2429 -        /* ----------------- generic input stream methods ------------------ */
  1.2430 -        /*
  1.2431 -         * The following methods are equivalent to their counterparts in
  1.2432 -         * InputStream, except that they interpret data block boundaries and
  1.2433 -         * read the requested data from within data blocks when in block data
  1.2434 -         * mode.
  1.2435 -         */
  1.2436 -
  1.2437 -        public int read() throws IOException {
  1.2438 -            if (blkmode) {
  1.2439 -                if (pos == end) {
  1.2440 -                    refill();
  1.2441 -                }
  1.2442 -                return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
  1.2443 -            } else {
  1.2444 -                return in.read();
  1.2445 -            }
  1.2446 -        }
  1.2447 -
  1.2448 -        public int read(byte[] b, int off, int len) throws IOException {
  1.2449 -            return read(b, off, len, false);
  1.2450 -        }
  1.2451 -
  1.2452 -        public long skip(long len) throws IOException {
  1.2453 -            long remain = len;
  1.2454 -            while (remain > 0) {
  1.2455 -                if (blkmode) {
  1.2456 -                    if (pos == end) {
  1.2457 -                        refill();
  1.2458 -                    }
  1.2459 -                    if (end < 0) {
  1.2460 -                        break;
  1.2461 -                    }
  1.2462 -                    int nread = (int) Math.min(remain, end - pos);
  1.2463 -                    remain -= nread;
  1.2464 -                    pos += nread;
  1.2465 -                } else {
  1.2466 -                    int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
  1.2467 -                    if ((nread = in.read(buf, 0, nread)) < 0) {
  1.2468 -                        break;
  1.2469 -                    }
  1.2470 -                    remain -= nread;
  1.2471 -                }
  1.2472 -            }
  1.2473 -            return len - remain;
  1.2474 -        }
  1.2475 -
  1.2476 -        public int available() throws IOException {
  1.2477 -            if (blkmode) {
  1.2478 -                if ((pos == end) && (unread == 0)) {
  1.2479 -                    int n;
  1.2480 -                    while ((n = readBlockHeader(false)) == 0) ;
  1.2481 -                    switch (n) {
  1.2482 -                        case HEADER_BLOCKED:
  1.2483 -                            break;
  1.2484 -
  1.2485 -                        case -1:
  1.2486 -                            pos = 0;
  1.2487 -                            end = -1;
  1.2488 -                            break;
  1.2489 -
  1.2490 -                        default:
  1.2491 -                            pos = 0;
  1.2492 -                            end = 0;
  1.2493 -                            unread = n;
  1.2494 -                            break;
  1.2495 -                    }
  1.2496 -                }
  1.2497 -                // avoid unnecessary call to in.available() if possible
  1.2498 -                int unreadAvail = (unread > 0) ?
  1.2499 -                    Math.min(in.available(), unread) : 0;
  1.2500 -                return (end >= 0) ? (end - pos) + unreadAvail : 0;
  1.2501 -            } else {
  1.2502 -                return in.available();
  1.2503 -            }
  1.2504 -        }
  1.2505 -
  1.2506 -        public void close() throws IOException {
  1.2507 -            if (blkmode) {
  1.2508 -                pos = 0;
  1.2509 -                end = -1;
  1.2510 -                unread = 0;
  1.2511 -            }
  1.2512 -            in.close();
  1.2513 -        }
  1.2514 -
  1.2515 -        /**
  1.2516 -         * Attempts to read len bytes into byte array b at offset off.  Returns
  1.2517 -         * the number of bytes read, or -1 if the end of stream/block data has
  1.2518 -         * been reached.  If copy is true, reads values into an intermediate
  1.2519 -         * buffer before copying them to b (to avoid exposing a reference to
  1.2520 -         * b).
  1.2521 -         */
  1.2522 -        int read(byte[] b, int off, int len, boolean copy) throws IOException {
  1.2523 -            if (len == 0) {
  1.2524 -                return 0;
  1.2525 -            } else if (blkmode) {
  1.2526 -                if (pos == end) {
  1.2527 -                    refill();
  1.2528 -                }
  1.2529 -                if (end < 0) {
  1.2530 -                    return -1;
  1.2531 -                }
  1.2532 -                int nread = Math.min(len, end - pos);
  1.2533 -                System.arraycopy(buf, pos, b, off, nread);
  1.2534 -                pos += nread;
  1.2535 -                return nread;
  1.2536 -            } else if (copy) {
  1.2537 -                int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
  1.2538 -                if (nread > 0) {
  1.2539 -                    System.arraycopy(buf, 0, b, off, nread);
  1.2540 -                }
  1.2541 -                return nread;
  1.2542 -            } else {
  1.2543 -                return in.read(b, off, len);
  1.2544 -            }
  1.2545 -        }
  1.2546 -
  1.2547 -        /* ----------------- primitive data input methods ------------------ */
  1.2548 -        /*
  1.2549 -         * The following methods are equivalent to their counterparts in
  1.2550 -         * DataInputStream, except that they interpret data block boundaries
  1.2551 -         * and read the requested data from within data blocks when in block
  1.2552 -         * data mode.
  1.2553 -         */
  1.2554 -
  1.2555 -        public void readFully(byte[] b) throws IOException {
  1.2556 -            readFully(b, 0, b.length, false);
  1.2557 -        }
  1.2558 -
  1.2559 -        public void readFully(byte[] b, int off, int len) throws IOException {
  1.2560 -            readFully(b, off, len, false);
  1.2561 -        }
  1.2562 -
  1.2563 -        public void readFully(byte[] b, int off, int len, boolean copy)
  1.2564 -            throws IOException
  1.2565 -        {
  1.2566 -            while (len > 0) {
  1.2567 -                int n = read(b, off, len, copy);
  1.2568 -                if (n < 0) {
  1.2569 -                    throw new EOFException();
  1.2570 -                }
  1.2571 -                off += n;
  1.2572 -                len -= n;
  1.2573 -            }
  1.2574 -        }
  1.2575 -
  1.2576 -        public int skipBytes(int n) throws IOException {
  1.2577 -            return din.skipBytes(n);
  1.2578 -        }
  1.2579 -
  1.2580 -        public boolean readBoolean() throws IOException {
  1.2581 -            int v = read();
  1.2582 -            if (v < 0) {
  1.2583 -                throw new EOFException();
  1.2584 -            }
  1.2585 -            return (v != 0);
  1.2586 -        }
  1.2587 -
  1.2588 -        public byte readByte() throws IOException {
  1.2589 -            int v = read();
  1.2590 -            if (v < 0) {
  1.2591 -                throw new EOFException();
  1.2592 -            }
  1.2593 -            return (byte) v;
  1.2594 -        }
  1.2595 -
  1.2596 -        public int readUnsignedByte() throws IOException {
  1.2597 -            int v = read();
  1.2598 -            if (v < 0) {
  1.2599 -                throw new EOFException();
  1.2600 -            }
  1.2601 -            return v;
  1.2602 -        }
  1.2603 -
  1.2604 -        public char readChar() throws IOException {
  1.2605 -            if (!blkmode) {
  1.2606 -                pos = 0;
  1.2607 -                in.readFully(buf, 0, 2);
  1.2608 -            } else if (end - pos < 2) {
  1.2609 -                return din.readChar();
  1.2610 -            }
  1.2611 -            char v = Bits.getChar(buf, pos);
  1.2612 -            pos += 2;
  1.2613 -            return v;
  1.2614 -        }
  1.2615 -
  1.2616 -        public short readShort() throws IOException {
  1.2617 -            if (!blkmode) {
  1.2618 -                pos = 0;
  1.2619 -                in.readFully(buf, 0, 2);
  1.2620 -            } else if (end - pos < 2) {
  1.2621 -                return din.readShort();
  1.2622 -            }
  1.2623 -            short v = Bits.getShort(buf, pos);
  1.2624 -            pos += 2;
  1.2625 -            return v;
  1.2626 -        }
  1.2627 -
  1.2628 -        public int readUnsignedShort() throws IOException {
  1.2629 -            if (!blkmode) {
  1.2630 -                pos = 0;
  1.2631 -                in.readFully(buf, 0, 2);
  1.2632 -            } else if (end - pos < 2) {
  1.2633 -                return din.readUnsignedShort();
  1.2634 -            }
  1.2635 -            int v = Bits.getShort(buf, pos) & 0xFFFF;
  1.2636 -            pos += 2;
  1.2637 -            return v;
  1.2638 -        }
  1.2639 -
  1.2640 -        public int readInt() throws IOException {
  1.2641 -            if (!blkmode) {
  1.2642 -                pos = 0;
  1.2643 -                in.readFully(buf, 0, 4);
  1.2644 -            } else if (end - pos < 4) {
  1.2645 -                return din.readInt();
  1.2646 -            }
  1.2647 -            int v = Bits.getInt(buf, pos);
  1.2648 -            pos += 4;
  1.2649 -            return v;
  1.2650 -        }
  1.2651 -
  1.2652 -        public float readFloat() throws IOException {
  1.2653 -            if (!blkmode) {
  1.2654 -                pos = 0;
  1.2655 -                in.readFully(buf, 0, 4);
  1.2656 -            } else if (end - pos < 4) {
  1.2657 -                return din.readFloat();
  1.2658 -            }
  1.2659 -            float v = Bits.getFloat(buf, pos);
  1.2660 -            pos += 4;
  1.2661 -            return v;
  1.2662 -        }
  1.2663 -
  1.2664 -        public long readLong() throws IOException {
  1.2665 -            if (!blkmode) {
  1.2666 -                pos = 0;
  1.2667 -                in.readFully(buf, 0, 8);
  1.2668 -            } else if (end - pos < 8) {
  1.2669 -                return din.readLong();
  1.2670 -            }
  1.2671 -            long v = Bits.getLong(buf, pos);
  1.2672 -            pos += 8;
  1.2673 -            return v;
  1.2674 -        }
  1.2675 -
  1.2676 -        public double readDouble() throws IOException {
  1.2677 -            if (!blkmode) {
  1.2678 -                pos = 0;
  1.2679 -                in.readFully(buf, 0, 8);
  1.2680 -            } else if (end - pos < 8) {
  1.2681 -                return din.readDouble();
  1.2682 -            }
  1.2683 -            double v = Bits.getDouble(buf, pos);
  1.2684 -            pos += 8;
  1.2685 -            return v;
  1.2686 -        }
  1.2687 -
  1.2688 -        public String readUTF() throws IOException {
  1.2689 -            return readUTFBody(readUnsignedShort());
  1.2690 -        }
  1.2691 -
  1.2692 -        public String readLine() throws IOException {
  1.2693 -            return din.readLine();      // deprecated, not worth optimizing
  1.2694 -        }
  1.2695 -
  1.2696 -        /* -------------- primitive data array input methods --------------- */
  1.2697 -        /*
  1.2698 -         * The following methods read in spans of primitive data values.
  1.2699 -         * Though equivalent to calling the corresponding primitive read
  1.2700 -         * methods repeatedly, these methods are optimized for reading groups
  1.2701 -         * of primitive data values more efficiently.
  1.2702 -         */
  1.2703 -
  1.2704 -        void readBooleans(boolean[] v, int off, int len) throws IOException {
  1.2705 -            int stop, endoff = off + len;
  1.2706 -            while (off < endoff) {
  1.2707 -                if (!blkmode) {
  1.2708 -                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
  1.2709 -                    in.readFully(buf, 0, span);
  1.2710 -                    stop = off + span;
  1.2711 -                    pos = 0;
  1.2712 -                } else if (end - pos < 1) {
  1.2713 -                    v[off++] = din.readBoolean();
  1.2714 -                    continue;
  1.2715 -                } else {
  1.2716 -                    stop = Math.min(endoff, off + end - pos);
  1.2717 -                }
  1.2718 -
  1.2719 -                while (off < stop) {
  1.2720 -                    v[off++] = Bits.getBoolean(buf, pos++);
  1.2721 -                }
  1.2722 -            }
  1.2723 -        }
  1.2724 -
  1.2725 -        void readChars(char[] v, int off, int len) throws IOException {
  1.2726 -            int stop, endoff = off + len;
  1.2727 -            while (off < endoff) {
  1.2728 -                if (!blkmode) {
  1.2729 -                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
  1.2730 -                    in.readFully(buf, 0, span << 1);
  1.2731 -                    stop = off + span;
  1.2732 -                    pos = 0;
  1.2733 -                } else if (end - pos < 2) {
  1.2734 -                    v[off++] = din.readChar();
  1.2735 -                    continue;
  1.2736 -                } else {
  1.2737 -                    stop = Math.min(endoff, off + ((end - pos) >> 1));
  1.2738 -                }
  1.2739 -
  1.2740 -                while (off < stop) {
  1.2741 -                    v[off++] = Bits.getChar(buf, pos);
  1.2742 -                    pos += 2;
  1.2743 -                }
  1.2744 -            }
  1.2745 -        }
  1.2746 -
  1.2747 -        void readShorts(short[] v, int off, int len) throws IOException {
  1.2748 -            int stop, endoff = off + len;
  1.2749 -            while (off < endoff) {
  1.2750 -                if (!blkmode) {
  1.2751 -                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
  1.2752 -                    in.readFully(buf, 0, span << 1);
  1.2753 -                    stop = off + span;
  1.2754 -                    pos = 0;
  1.2755 -                } else if (end - pos < 2) {
  1.2756 -                    v[off++] = din.readShort();
  1.2757 -                    continue;
  1.2758 -                } else {
  1.2759 -                    stop = Math.min(endoff, off + ((end - pos) >> 1));
  1.2760 -                }
  1.2761 -
  1.2762 -                while (off < stop) {
  1.2763 -                    v[off++] = Bits.getShort(buf, pos);
  1.2764 -                    pos += 2;
  1.2765 -                }
  1.2766 -            }
  1.2767 -        }
  1.2768 -
  1.2769 -        void readInts(int[] v, int off, int len) throws IOException {
  1.2770 -            int stop, endoff = off + len;
  1.2771 -            while (off < endoff) {
  1.2772 -                if (!blkmode) {
  1.2773 -                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
  1.2774 -                    in.readFully(buf, 0, span << 2);
  1.2775 -                    stop = off + span;
  1.2776 -                    pos = 0;
  1.2777 -                } else if (end - pos < 4) {
  1.2778 -                    v[off++] = din.readInt();
  1.2779 -                    continue;
  1.2780 -                } else {
  1.2781 -                    stop = Math.min(endoff, off + ((end - pos) >> 2));
  1.2782 -                }
  1.2783 -
  1.2784 -                while (off < stop) {
  1.2785 -                    v[off++] = Bits.getInt(buf, pos);
  1.2786 -                    pos += 4;
  1.2787 -                }
  1.2788 -            }
  1.2789 -        }
  1.2790 -
  1.2791 -        void readFloats(float[] v, int off, int len) throws IOException {
  1.2792 -            int span, endoff = off + len;
  1.2793 -            while (off < endoff) {
  1.2794 -                if (!blkmode) {
  1.2795 -                    span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
  1.2796 -                    in.readFully(buf, 0, span << 2);
  1.2797 -                    pos = 0;
  1.2798 -                } else if (end - pos < 4) {
  1.2799 -                    v[off++] = din.readFloat();
  1.2800 -                    continue;
  1.2801 -                } else {
  1.2802 -                    span = Math.min(endoff - off, ((end - pos) >> 2));
  1.2803 -                }
  1.2804 -
  1.2805 -                bytesToFloats(buf, pos, v, off, span);
  1.2806 -                off += span;
  1.2807 -                pos += span << 2;
  1.2808 -            }
  1.2809 -        }
  1.2810 -
  1.2811 -        void readLongs(long[] v, int off, int len) throws IOException {
  1.2812 -            int stop, endoff = off + len;
  1.2813 -            while (off < endoff) {
  1.2814 -                if (!blkmode) {
  1.2815 -                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
  1.2816 -                    in.readFully(buf, 0, span << 3);
  1.2817 -                    stop = off + span;
  1.2818 -                    pos = 0;
  1.2819 -                } else if (end - pos < 8) {
  1.2820 -                    v[off++] = din.readLong();
  1.2821 -                    continue;
  1.2822 -                } else {
  1.2823 -                    stop = Math.min(endoff, off + ((end - pos) >> 3));
  1.2824 -                }
  1.2825 -
  1.2826 -                while (off < stop) {
  1.2827 -                    v[off++] = Bits.getLong(buf, pos);
  1.2828 -                    pos += 8;
  1.2829 -                }
  1.2830 -            }
  1.2831 -        }
  1.2832 -
  1.2833 -        void readDoubles(double[] v, int off, int len) throws IOException {
  1.2834 -            int span, endoff = off + len;
  1.2835 -            while (off < endoff) {
  1.2836 -                if (!blkmode) {
  1.2837 -                    span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
  1.2838 -                    in.readFully(buf, 0, span << 3);
  1.2839 -                    pos = 0;
  1.2840 -                } else if (end - pos < 8) {
  1.2841 -                    v[off++] = din.readDouble();
  1.2842 -                    continue;
  1.2843 -                } else {
  1.2844 -                    span = Math.min(endoff - off, ((end - pos) >> 3));
  1.2845 -                }
  1.2846 -
  1.2847 -                bytesToDoubles(buf, pos, v, off, span);
  1.2848 -                off += span;
  1.2849 -                pos += span << 3;
  1.2850 -            }
  1.2851 -        }
  1.2852 -
  1.2853 -        /**
  1.2854 -         * Reads in string written in "long" UTF format.  "Long" UTF format is
  1.2855 -         * identical to standard UTF, except that it uses an 8 byte header
  1.2856 -         * (instead of the standard 2 bytes) to convey the UTF encoding length.
  1.2857 -         */
  1.2858 -        String readLongUTF() throws IOException {
  1.2859 -            return readUTFBody(readLong());
  1.2860 -        }
  1.2861 -
  1.2862 -        /**
  1.2863 -         * Reads in the "body" (i.e., the UTF representation minus the 2-byte
  1.2864 -         * or 8-byte length header) of a UTF encoding, which occupies the next
  1.2865 -         * utflen bytes.
  1.2866 -         */
  1.2867 -        private String readUTFBody(long utflen) throws IOException {
  1.2868 -            StringBuilder sbuf = new StringBuilder();
  1.2869 -            if (!blkmode) {
  1.2870 -                end = pos = 0;
  1.2871 -            }
  1.2872 -
  1.2873 -            while (utflen > 0) {
  1.2874 -                int avail = end - pos;
  1.2875 -                if (avail >= 3 || (long) avail == utflen) {
  1.2876 -                    utflen -= readUTFSpan(sbuf, utflen);
  1.2877 -                } else {
  1.2878 -                    if (blkmode) {
  1.2879 -                        // near block boundary, read one byte at a time
  1.2880 -                        utflen -= readUTFChar(sbuf, utflen);
  1.2881 -                    } else {
  1.2882 -                        // shift and refill buffer manually
  1.2883 -                        if (avail > 0) {
  1.2884 -                            System.arraycopy(buf, pos, buf, 0, avail);
  1.2885 -                        }
  1.2886 -                        pos = 0;
  1.2887 -                        end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
  1.2888 -                        in.readFully(buf, avail, end - avail);
  1.2889 -                    }
  1.2890 -                }
  1.2891 -            }
  1.2892 -
  1.2893 -            return sbuf.toString();
  1.2894 -        }
  1.2895 -
  1.2896 -        /**
  1.2897 -         * Reads span of UTF-encoded characters out of internal buffer
  1.2898 -         * (starting at offset pos and ending at or before offset end),
  1.2899 -         * consuming no more than utflen bytes.  Appends read characters to
  1.2900 -         * sbuf.  Returns the number of bytes consumed.
  1.2901 -         */
  1.2902 -        private long readUTFSpan(StringBuilder sbuf, long utflen)
  1.2903 -            throws IOException
  1.2904 -        {
  1.2905 -            int cpos = 0;
  1.2906 -            int start = pos;
  1.2907 -            int avail = Math.min(end - pos, CHAR_BUF_SIZE);
  1.2908 -            // stop short of last char unless all of utf bytes in buffer
  1.2909 -            int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
  1.2910 -            boolean outOfBounds = false;
  1.2911 -
  1.2912 -            try {
  1.2913 -                while (pos < stop) {
  1.2914 -                    int b1, b2, b3;
  1.2915 -                    b1 = buf[pos++] & 0xFF;
  1.2916 -                    switch (b1 >> 4) {
  1.2917 -                        case 0:
  1.2918 -                        case 1:
  1.2919 -                        case 2:
  1.2920 -                        case 3:
  1.2921 -                        case 4:
  1.2922 -                        case 5:
  1.2923 -                        case 6:
  1.2924 -                        case 7:   // 1 byte format: 0xxxxxxx
  1.2925 -                            cbuf[cpos++] = (char) b1;
  1.2926 -                            break;
  1.2927 -
  1.2928 -                        case 12:
  1.2929 -                        case 13:  // 2 byte format: 110xxxxx 10xxxxxx
  1.2930 -                            b2 = buf[pos++];
  1.2931 -                            if ((b2 & 0xC0) != 0x80) {
  1.2932 -                                throw new UTFDataFormatException();
  1.2933 -                            }
  1.2934 -                            cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
  1.2935 -                                                   ((b2 & 0x3F) << 0));
  1.2936 -                            break;
  1.2937 -
  1.2938 -                        case 14:  // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
  1.2939 -                            b3 = buf[pos + 1];
  1.2940 -                            b2 = buf[pos + 0];
  1.2941 -                            pos += 2;
  1.2942 -                            if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
  1.2943 -                                throw new UTFDataFormatException();
  1.2944 -                            }
  1.2945 -                            cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
  1.2946 -                                                   ((b2 & 0x3F) << 6) |
  1.2947 -                                                   ((b3 & 0x3F) << 0));
  1.2948 -                            break;
  1.2949 -
  1.2950 -                        default:  // 10xx xxxx, 1111 xxxx
  1.2951 -                            throw new UTFDataFormatException();
  1.2952 -                    }
  1.2953 -                }
  1.2954 -            } catch (ArrayIndexOutOfBoundsException ex) {
  1.2955 -                outOfBounds = true;
  1.2956 -            } finally {
  1.2957 -                if (outOfBounds || (pos - start) > utflen) {
  1.2958 -                    /*
  1.2959 -                     * Fix for 4450867: if a malformed utf char causes the
  1.2960 -                     * conversion loop to scan past the expected end of the utf
  1.2961 -                     * string, only consume the expected number of utf bytes.
  1.2962 -                     */
  1.2963 -                    pos = start + (int) utflen;
  1.2964 -                    throw new UTFDataFormatException();
  1.2965 -                }
  1.2966 -            }
  1.2967 -
  1.2968 -            sbuf.append(cbuf, 0, cpos);
  1.2969 -            return pos - start;
  1.2970 -        }
  1.2971 -
  1.2972 -        /**
  1.2973 -         * Reads in single UTF-encoded character one byte at a time, appends
  1.2974 -         * the character to sbuf, and returns the number of bytes consumed.
  1.2975 -         * This method is used when reading in UTF strings written in block
  1.2976 -         * data mode to handle UTF-encoded characters which (potentially)
  1.2977 -         * straddle block-data boundaries.
  1.2978 -         */
  1.2979 -        private int readUTFChar(StringBuilder sbuf, long utflen)
  1.2980 -            throws IOException
  1.2981 -        {
  1.2982 -            int b1, b2, b3;
  1.2983 -            b1 = readByte() & 0xFF;
  1.2984 -            switch (b1 >> 4) {
  1.2985 -                case 0:
  1.2986 -                case 1:
  1.2987 -                case 2:
  1.2988 -                case 3:
  1.2989 -                case 4:
  1.2990 -                case 5:
  1.2991 -                case 6:
  1.2992 -                case 7:     // 1 byte format: 0xxxxxxx
  1.2993 -                    sbuf.append((char) b1);
  1.2994 -                    return 1;
  1.2995 -
  1.2996 -                case 12:
  1.2997 -                case 13:    // 2 byte format: 110xxxxx 10xxxxxx
  1.2998 -                    if (utflen < 2) {
  1.2999 -                        throw new UTFDataFormatException();
  1.3000 -                    }
  1.3001 -                    b2 = readByte();
  1.3002 -                    if ((b2 & 0xC0) != 0x80) {
  1.3003 -                        throw new UTFDataFormatException();
  1.3004 -                    }
  1.3005 -                    sbuf.append((char) (((b1 & 0x1F) << 6) |
  1.3006 -                                        ((b2 & 0x3F) << 0)));
  1.3007 -                    return 2;
  1.3008 -
  1.3009 -                case 14:    // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
  1.3010 -                    if (utflen < 3) {
  1.3011 -                        if (utflen == 2) {
  1.3012 -                            readByte();         // consume remaining byte
  1.3013 -                        }
  1.3014 -                        throw new UTFDataFormatException();
  1.3015 -                    }
  1.3016 -                    b2 = readByte();
  1.3017 -                    b3 = readByte();
  1.3018 -                    if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
  1.3019 -                        throw new UTFDataFormatException();
  1.3020 -                    }
  1.3021 -                    sbuf.append((char) (((b1 & 0x0F) << 12) |
  1.3022 -                                        ((b2 & 0x3F) << 6) |
  1.3023 -                                        ((b3 & 0x3F) << 0)));
  1.3024 -                    return 3;
  1.3025 -
  1.3026 -                default:   // 10xx xxxx, 1111 xxxx
  1.3027 -                    throw new UTFDataFormatException();
  1.3028 -            }
  1.3029 -        }
  1.3030 -    }
  1.3031 -
  1.3032 -    /**
  1.3033 -     * Unsynchronized table which tracks wire handle to object mappings, as
  1.3034 -     * well as ClassNotFoundExceptions associated with deserialized objects.
  1.3035 -     * This class implements an exception-propagation algorithm for
  1.3036 -     * determining which objects should have ClassNotFoundExceptions associated
  1.3037 -     * with them, taking into account cycles and discontinuities (e.g., skipped
  1.3038 -     * fields) in the object graph.
  1.3039 -     *
  1.3040 -     * <p>General use of the table is as follows: during deserialization, a
  1.3041 -     * given object is first assigned a handle by calling the assign method.
  1.3042 -     * This method leaves the assigned handle in an "open" state, wherein
  1.3043 -     * dependencies on the exception status of other handles can be registered
  1.3044 -     * by calling the markDependency method, or an exception can be directly
  1.3045 -     * associated with the handle by calling markException.  When a handle is
  1.3046 -     * tagged with an exception, the HandleTable assumes responsibility for
  1.3047 -     * propagating the exception to any other objects which depend
  1.3048 -     * (transitively) on the exception-tagged object.
  1.3049 -     *
  1.3050 -     * <p>Once all exception information/dependencies for the handle have been
  1.3051 -     * registered, the handle should be "closed" by calling the finish method
  1.3052 -     * on it.  The act of finishing a handle allows the exception propagation
  1.3053 -     * algorithm to aggressively prune dependency links, lessening the
  1.3054 -     * performance/memory impact of exception tracking.
  1.3055 -     *
  1.3056 -     * <p>Note that the exception propagation algorithm used depends on handles
  1.3057 -     * being assigned/finished in LIFO order; however, for simplicity as well
  1.3058 -     * as memory conservation, it does not enforce this constraint.
  1.3059 -     */
  1.3060 -    // REMIND: add full description of exception propagation algorithm?
  1.3061 -    private static class HandleTable {
  1.3062 -
  1.3063 -        /* status codes indicating whether object has associated exception */
  1.3064 -        private static final byte STATUS_OK = 1;
  1.3065 -        private static final byte STATUS_UNKNOWN = 2;
  1.3066 -        private static final byte STATUS_EXCEPTION = 3;
  1.3067 -
  1.3068 -        /** array mapping handle -> object status */
  1.3069 -        byte[] status;
  1.3070 -        /** array mapping handle -> object/exception (depending on status) */
  1.3071 -        Object[] entries;
  1.3072 -        /** array mapping handle -> list of dependent handles (if any) */
  1.3073 -        HandleList[] deps;
  1.3074 -        /** lowest unresolved dependency */
  1.3075 -        int lowDep = -1;
  1.3076 -        /** number of handles in table */
  1.3077 -        int size = 0;
  1.3078 -
  1.3079 -        /**
  1.3080 -         * Creates handle table with the given initial capacity.
  1.3081 -         */
  1.3082 -        HandleTable(int initialCapacity) {
  1.3083 -            status = new byte[initialCapacity];
  1.3084 -            entries = new Object[initialCapacity];
  1.3085 -            deps = new HandleList[initialCapacity];
  1.3086 -        }
  1.3087 -
  1.3088 -        /**
  1.3089 -         * Assigns next available handle to given object, and returns assigned
  1.3090 -         * handle.  Once object has been completely deserialized (and all
  1.3091 -         * dependencies on other objects identified), the handle should be
  1.3092 -         * "closed" by passing it to finish().
  1.3093 -         */
  1.3094 -        int assign(Object obj) {
  1.3095 -            if (size >= entries.length) {
  1.3096 -                grow();
  1.3097 -            }
  1.3098 -            status[size] = STATUS_UNKNOWN;
  1.3099 -            entries[size] = obj;
  1.3100 -            return size++;
  1.3101 -        }
  1.3102 -
  1.3103 -        /**
  1.3104 -         * Registers a dependency (in exception status) of one handle on
  1.3105 -         * another.  The dependent handle must be "open" (i.e., assigned, but
  1.3106 -         * not finished yet).  No action is taken if either dependent or target
  1.3107 -         * handle is NULL_HANDLE.
  1.3108 -         */
  1.3109 -        void markDependency(int dependent, int target) {
  1.3110 -            if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
  1.3111 -                return;
  1.3112 -            }
  1.3113 -            switch (status[dependent]) {
  1.3114 -
  1.3115 -                case STATUS_UNKNOWN:
  1.3116 -                    switch (status[target]) {
  1.3117 -                        case STATUS_OK:
  1.3118 -                            // ignore dependencies on objs with no exception
  1.3119 -                            break;
  1.3120 -
  1.3121 -                        case STATUS_EXCEPTION:
  1.3122 -                            // eagerly propagate exception
  1.3123 -                            markException(dependent,
  1.3124 -                                (ClassNotFoundException) entries[target]);
  1.3125 -                            break;
  1.3126 -
  1.3127 -                        case STATUS_UNKNOWN:
  1.3128 -                            // add to dependency list of target
  1.3129 -                            if (deps[target] == null) {
  1.3130 -                                deps[target] = new HandleList();
  1.3131 -                            }
  1.3132 -                            deps[target].add(dependent);
  1.3133 -
  1.3134 -                            // remember lowest unresolved target seen
  1.3135 -                            if (lowDep < 0 || lowDep > target) {
  1.3136 -                                lowDep = target;
  1.3137 -                            }
  1.3138 -                            break;
  1.3139 -
  1.3140 -                        default:
  1.3141 -                            throw new InternalError();
  1.3142 -                    }
  1.3143 -                    break;
  1.3144 -
  1.3145 -                case STATUS_EXCEPTION:
  1.3146 -                    break;
  1.3147 -
  1.3148 -                default:
  1.3149 -                    throw new InternalError();
  1.3150 -            }
  1.3151 -        }
  1.3152 -
  1.3153 -        /**
  1.3154 -         * Associates a ClassNotFoundException (if one not already associated)
  1.3155 -         * with the currently active handle and propagates it to other
  1.3156 -         * referencing objects as appropriate.  The specified handle must be
  1.3157 -         * "open" (i.e., assigned, but not finished yet).
  1.3158 -         */
  1.3159 -        void markException(int handle, ClassNotFoundException ex) {
  1.3160 -            switch (status[handle]) {
  1.3161 -                case STATUS_UNKNOWN:
  1.3162 -                    status[handle] = STATUS_EXCEPTION;
  1.3163 -                    entries[handle] = ex;
  1.3164 -
  1.3165 -                    // propagate exception to dependents
  1.3166 -                    HandleList dlist = deps[handle];
  1.3167 -                    if (dlist != null) {
  1.3168 -                        int ndeps = dlist.size();
  1.3169 -                        for (int i = 0; i < ndeps; i++) {
  1.3170 -                            markException(dlist.get(i), ex);
  1.3171 -                        }
  1.3172 -                        deps[handle] = null;
  1.3173 -                    }
  1.3174 -                    break;
  1.3175 -
  1.3176 -                case STATUS_EXCEPTION:
  1.3177 -                    break;
  1.3178 -
  1.3179 -                default:
  1.3180 -                    throw new InternalError();
  1.3181 -            }
  1.3182 -        }
  1.3183 -
  1.3184 -        /**
  1.3185 -         * Marks given handle as finished, meaning that no new dependencies
  1.3186 -         * will be marked for handle.  Calls to the assign and finish methods
  1.3187 -         * must occur in LIFO order.
  1.3188 -         */
  1.3189 -        void finish(int handle) {
  1.3190 -            int end;
  1.3191 -            if (lowDep < 0) {
  1.3192 -                // no pending unknowns, only resolve current handle
  1.3193 -                end = handle + 1;
  1.3194 -            } else if (lowDep >= handle) {
  1.3195 -                // pending unknowns now clearable, resolve all upward handles
  1.3196 -                end = size;
  1.3197 -                lowDep = -1;
  1.3198 -            } else {
  1.3199 -                // unresolved backrefs present, can't resolve anything yet
  1.3200 -                return;
  1.3201 -            }
  1.3202 -
  1.3203 -            // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
  1.3204 -            for (int i = handle; i < end; i++) {
  1.3205 -                switch (status[i]) {
  1.3206 -                    case STATUS_UNKNOWN:
  1.3207 -                        status[i] = STATUS_OK;
  1.3208 -                        deps[i] = null;
  1.3209 -                        break;
  1.3210 -
  1.3211 -                    case STATUS_OK:
  1.3212 -                    case STATUS_EXCEPTION:
  1.3213 -                        break;
  1.3214 -
  1.3215 -                    default:
  1.3216 -                        throw new InternalError();
  1.3217 -                }
  1.3218 -            }
  1.3219 -        }
  1.3220 -
  1.3221 -        /**
  1.3222 -         * Assigns a new object to the given handle.  The object previously
  1.3223 -         * associated with the handle is forgotten.  This method has no effect
  1.3224 -         * if the given handle already has an exception associated with it.
  1.3225 -         * This method may be called at any time after the handle is assigned.
  1.3226 -         */
  1.3227 -        void setObject(int handle, Object obj) {
  1.3228 -            switch (status[handle]) {
  1.3229 -                case STATUS_UNKNOWN:
  1.3230 -                case STATUS_OK:
  1.3231 -                    entries[handle] = obj;
  1.3232 -                    break;
  1.3233 -
  1.3234 -                case STATUS_EXCEPTION:
  1.3235 -                    break;
  1.3236 -
  1.3237 -                default:
  1.3238 -                    throw new InternalError();
  1.3239 -            }
  1.3240 -        }
  1.3241 -
  1.3242 -        /**
  1.3243 -         * Looks up and returns object associated with the given handle.
  1.3244 -         * Returns null if the given handle is NULL_HANDLE, or if it has an
  1.3245 -         * associated ClassNotFoundException.
  1.3246 -         */
  1.3247 -        Object lookupObject(int handle) {
  1.3248 -            return (handle != NULL_HANDLE &&
  1.3249 -                    status[handle] != STATUS_EXCEPTION) ?
  1.3250 -                entries[handle] : null;
  1.3251 -        }
  1.3252 -
  1.3253 -        /**
  1.3254 -         * Looks up and returns ClassNotFoundException associated with the
  1.3255 -         * given handle.  Returns null if the given handle is NULL_HANDLE, or
  1.3256 -         * if there is no ClassNotFoundException associated with the handle.
  1.3257 -         */
  1.3258 -        ClassNotFoundException lookupException(int handle) {
  1.3259 -            return (handle != NULL_HANDLE &&
  1.3260 -                    status[handle] == STATUS_EXCEPTION) ?
  1.3261 -                (ClassNotFoundException) entries[handle] : null;
  1.3262 -        }
  1.3263 -
  1.3264 -        /**
  1.3265 -         * Resets table to its initial state.
  1.3266 -         */
  1.3267 -        void clear() {
  1.3268 -            Arrays.fill(status, 0, size, (byte) 0);
  1.3269 -            Arrays.fill(entries, 0, size, null);
  1.3270 -            Arrays.fill(deps, 0, size, null);
  1.3271 -            lowDep = -1;
  1.3272 -            size = 0;
  1.3273 -        }
  1.3274 -
  1.3275 -        /**
  1.3276 -         * Returns number of handles registered in table.
  1.3277 -         */
  1.3278 -        int size() {
  1.3279 -            return size;
  1.3280 -        }
  1.3281 -
  1.3282 -        /**
  1.3283 -         * Expands capacity of internal arrays.
  1.3284 -         */
  1.3285 -        private void grow() {
  1.3286 -            int newCapacity = (entries.length << 1) + 1;
  1.3287 -
  1.3288 -            byte[] newStatus = new byte[newCapacity];
  1.3289 -            Object[] newEntries = new Object[newCapacity];
  1.3290 -            HandleList[] newDeps = new HandleList[newCapacity];
  1.3291 -
  1.3292 -            System.arraycopy(status, 0, newStatus, 0, size);
  1.3293 -            System.arraycopy(entries, 0, newEntries, 0, size);
  1.3294 -            System.arraycopy(deps, 0, newDeps, 0, size);
  1.3295 -
  1.3296 -            status = newStatus;
  1.3297 -            entries = newEntries;
  1.3298 -            deps = newDeps;
  1.3299 -        }
  1.3300 -
  1.3301 -        /**
  1.3302 -         * Simple growable list of (integer) handles.
  1.3303 -         */
  1.3304 -        private static class HandleList {
  1.3305 -            private int[] list = new int[4];
  1.3306 -            private int size = 0;
  1.3307 -
  1.3308 -            public HandleList() {
  1.3309 -            }
  1.3310 -
  1.3311 -            public void add(int handle) {
  1.3312 -                if (size >= list.length) {
  1.3313 -                    int[] newList = new int[list.length << 1];
  1.3314 -                    System.arraycopy(list, 0, newList, 0, list.length);
  1.3315 -                    list = newList;
  1.3316 -                }
  1.3317 -                list[size++] = handle;
  1.3318 -            }
  1.3319 -
  1.3320 -            public int get(int index) {
  1.3321 -                if (index >= size) {
  1.3322 -                    throw new ArrayIndexOutOfBoundsException();
  1.3323 -                }
  1.3324 -                return list[index];
  1.3325 -            }
  1.3326 -
  1.3327 -            public int size() {
  1.3328 -                return size;
  1.3329 -            }
  1.3330 -        }
  1.3331 -    }
  1.3332 -
  1.3333 -    /**
  1.3334 -     * Method for cloning arrays in case of using unsharing reading
  1.3335 -     */
  1.3336 -    private static Object cloneArray(Object array) {
  1.3337 -        if (array instanceof Object[]) {
  1.3338 -            return ((Object[]) array).clone();
  1.3339 -        } else if (array instanceof boolean[]) {
  1.3340 -            return ((boolean[]) array).clone();
  1.3341 -        } else if (array instanceof byte[]) {
  1.3342 -            return ((byte[]) array).clone();
  1.3343 -        } else if (array instanceof char[]) {
  1.3344 -            return ((char[]) array).clone();
  1.3345 -        } else if (array instanceof double[]) {
  1.3346 -            return ((double[]) array).clone();
  1.3347 -        } else if (array instanceof float[]) {
  1.3348 -            return ((float[]) array).clone();
  1.3349 -        } else if (array instanceof int[]) {
  1.3350 -            return ((int[]) array).clone();
  1.3351 -        } else if (array instanceof long[]) {
  1.3352 -            return ((long[]) array).clone();
  1.3353 -        } else if (array instanceof short[]) {
  1.3354 -            return ((short[]) array).clone();
  1.3355 -        } else {
  1.3356 -            throw new AssertionError();
  1.3357 -        }
  1.3358 -    }
  1.3359 -
  1.3360 -}