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