1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.  Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 * or visit www.oracle.com if you need additional information or have any
24 * questions.
25 */
26
27package java.io;
28
29import java.io.ObjectStreamClass.WeakClassKey;
30import java.lang.ref.ReferenceQueue;
31import java.lang.reflect.Array;
32import java.lang.reflect.Modifier;
33import java.lang.reflect.Proxy;
34import java.security.AccessControlContext;
35import java.security.AccessController;
36import java.security.PrivilegedAction;
37import java.security.PrivilegedActionException;
38import java.security.PrivilegedExceptionAction;
39import java.util.Arrays;
40import java.util.HashMap;
41import java.util.concurrent.ConcurrentHashMap;
42import java.util.concurrent.ConcurrentMap;
43import java.util.concurrent.atomic.AtomicBoolean;
44import static java.io.ObjectStreamClass.processQueue;
45import sun.reflect.misc.ReflectUtil;
46import dalvik.system.VMStack;
47
48/**
49 * An ObjectInputStream deserializes primitive data and objects previously
50 * written using an ObjectOutputStream.
51 *
52 * <p>ObjectOutputStream and ObjectInputStream can provide an application with
53 * persistent storage for graphs of objects when used with a FileOutputStream
54 * and FileInputStream respectively.  ObjectInputStream is used to recover
55 * those objects previously serialized. Other uses include passing objects
56 * between hosts using a socket stream or for marshaling and unmarshaling
57 * arguments and parameters in a remote communication system.
58 *
59 * <p>ObjectInputStream ensures that the types of all objects in the graph
60 * created from the stream match the classes present in the Java Virtual
61 * Machine.  Classes are loaded as required using the standard mechanisms.
62 *
63 * <p>Only objects that support the java.io.Serializable or
64 * java.io.Externalizable interface can be read from streams.
65 *
66 * <p>The method <code>readObject</code> is used to read an object from the
67 * stream.  Java's safe casting should be used to get the desired type.  In
68 * Java, strings and arrays are objects and are treated as objects during
69 * serialization. When read they need to be cast to the expected type.
70 *
71 * <p>Primitive data types can be read from the stream using the appropriate
72 * method on DataInput.
73 *
74 * <p>The default deserialization mechanism for objects restores the contents
75 * of each field to the value and type it had when it was written.  Fields
76 * declared as transient or static are ignored by the deserialization process.
77 * References to other objects cause those objects to be read from the stream
78 * as necessary.  Graphs of objects are restored correctly using a reference
79 * sharing mechanism.  New objects are always allocated when deserializing,
80 * which prevents existing objects from being overwritten.
81 *
82 * <p>Reading an object is analogous to running the constructors of a new
83 * object.  Memory is allocated for the object and initialized to zero (NULL).
84 * No-arg constructors are invoked for the non-serializable classes and then
85 * the fields of the serializable classes are restored from the stream starting
86 * with the serializable class closest to java.lang.object and finishing with
87 * the object's most specific class.
88 *
89 * <p>For example to read from a stream as written by the example in
90 * ObjectOutputStream:
91 * <br>
92 * <pre>
93 *      FileInputStream fis = new FileInputStream("t.tmp");
94 *      ObjectInputStream ois = new ObjectInputStream(fis);
95 *
96 *      int i = ois.readInt();
97 *      String today = (String) ois.readObject();
98 *      Date date = (Date) ois.readObject();
99 *
100 *      ois.close();
101 * </pre>
102 *
103 * <p>Classes control how they are serialized by implementing either the
104 * java.io.Serializable or java.io.Externalizable interfaces.
105 *
106 * <p>Implementing the Serializable interface allows object serialization to
107 * save and restore the entire state of the object and it allows classes to
108 * evolve between the time the stream is written and the time it is read.  It
109 * automatically traverses references between objects, saving and restoring
110 * entire graphs.
111 *
112 * <p>Serializable classes that require special handling during the
113 * serialization and deserialization process should implement the following
114 * methods:
115 *
116 * <pre>
117 * private void writeObject(java.io.ObjectOutputStream stream)
118 *     throws IOException;
119 * private void readObject(java.io.ObjectInputStream stream)
120 *     throws IOException, ClassNotFoundException;
121 * private void readObjectNoData()
122 *     throws ObjectStreamException;
123 * </pre>
124 *
125 * <p>The readObject method is responsible for reading and restoring the state
126 * of the object for its particular class using data written to the stream by
127 * the corresponding writeObject method.  The method does not need to concern
128 * itself with the state belonging to its superclasses or subclasses.  State is
129 * restored by reading data from the ObjectInputStream for the individual
130 * fields and making assignments to the appropriate fields of the object.
131 * Reading primitive data types is supported by DataInput.
132 *
133 * <p>Any attempt to read object data which exceeds the boundaries of the
134 * custom data written by the corresponding writeObject method will cause an
135 * OptionalDataException to be thrown with an eof field value of true.
136 * Non-object reads which exceed the end of the allotted data will reflect the
137 * end of data in the same way that they would indicate the end of the stream:
138 * bytewise reads will return -1 as the byte read or number of bytes read, and
139 * primitive reads will throw EOFExceptions.  If there is no corresponding
140 * writeObject method, then the end of default serialized data marks the end of
141 * the allotted data.
142 *
143 * <p>Primitive and object read calls issued from within a readExternal method
144 * behave in the same manner--if the stream is already positioned at the end of
145 * data written by the corresponding writeExternal method, object reads will
146 * throw OptionalDataExceptions with eof set to true, bytewise reads will
147 * return -1, and primitive reads will throw EOFExceptions.  Note that this
148 * behavior does not hold for streams written with the old
149 * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
150 * end of data written by writeExternal methods is not demarcated, and hence
151 * cannot be detected.
152 *
153 * <p>The readObjectNoData method is responsible for initializing the state of
154 * the object for its particular class in the event that the serialization
155 * stream does not list the given class as a superclass of the object being
156 * deserialized.  This may occur in cases where the receiving party uses a
157 * different version of the deserialized instance's class than the sending
158 * party, and the receiver's version extends classes that are not extended by
159 * the sender's version.  This may also occur if the serialization stream has
160 * been tampered; hence, readObjectNoData is useful for initializing
161 * deserialized objects properly despite a "hostile" or incomplete source
162 * stream.
163 *
164 * <p>Serialization does not read or assign values to the fields of any object
165 * that does not implement the java.io.Serializable interface.  Subclasses of
166 * Objects that are not serializable can be serializable. In this case the
167 * non-serializable class must have a no-arg constructor to allow its fields to
168 * be initialized.  In this case it is the responsibility of the subclass to
169 * save and restore the state of the non-serializable class. It is frequently
170 * the case that the fields of that class are accessible (public, package, or
171 * protected) or that there are get and set methods that can be used to restore
172 * the state.
173 *
174 * <p>Any exception that occurs while deserializing an object will be caught by
175 * the ObjectInputStream and abort the reading process.
176 *
177 * <p>Implementing the Externalizable interface allows the object to assume
178 * complete control over the contents and format of the object's serialized
179 * form.  The methods of the Externalizable interface, writeExternal and
180 * readExternal, are called to save and restore the objects state.  When
181 * implemented by a class they can write and read their own state using all of
182 * the methods of ObjectOutput and ObjectInput.  It is the responsibility of
183 * the objects to handle any versioning that occurs.
184 *
185 * <p>Enum constants are deserialized differently than ordinary serializable or
186 * externalizable objects.  The serialized form of an enum constant consists
187 * solely of its name; field values of the constant are not transmitted.  To
188 * deserialize an enum constant, ObjectInputStream reads the constant name from
189 * the stream; the deserialized constant is then obtained by calling the static
190 * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
191 * base type and the received constant name as arguments.  Like other
192 * serializable or externalizable objects, enum constants can function as the
193 * targets of back references appearing subsequently in the serialization
194 * stream.  The process by which enum constants are deserialized cannot be
195 * customized: any class-specific readObject, readObjectNoData, and readResolve
196 * methods defined by enum types are ignored during deserialization.
197 * Similarly, any serialPersistentFields or serialVersionUID field declarations
198 * are also ignored--all enum types have a fixed serialVersionUID of 0L.
199 *
200 * @author      Mike Warres
201 * @author      Roger Riggs
202 * @see java.io.DataInput
203 * @see java.io.ObjectOutputStream
204 * @see java.io.Serializable
205 * @see <a href="{@docRoot}openjdk-redirect.html?v=8&path=/platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
206 * @since   JDK1.1
207 */
208public class ObjectInputStream
209    extends InputStream implements ObjectInput, ObjectStreamConstants
210{
211
212    /** handle value representing null */
213    private static final int NULL_HANDLE = -1;
214
215    /** marker for unshared objects in internal handle table */
216    private static final Object unsharedMarker = new Object();
217
218    /** table mapping primitive type names to corresponding class objects */
219    private static final HashMap<String, Class<?>> primClasses
220        = new HashMap<>(8, 1.0F);
221    static {
222        primClasses.put("boolean", boolean.class);
223        primClasses.put("byte", byte.class);
224        primClasses.put("char", char.class);
225        primClasses.put("short", short.class);
226        primClasses.put("int", int.class);
227        primClasses.put("long", long.class);
228        primClasses.put("float", float.class);
229        primClasses.put("double", double.class);
230        primClasses.put("void", void.class);
231    }
232
233    private static class Caches {
234        /** cache of subclass security audit results */
235        static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
236            new ConcurrentHashMap<>();
237
238        /** queue for WeakReferences to audited subclasses */
239        static final ReferenceQueue<Class<?>> subclassAuditsQueue =
240            new ReferenceQueue<>();
241    }
242
243    /** filter stream for handling block data conversion */
244    private final BlockDataInputStream bin;
245    /** validation callback list */
246    private final ValidationList vlist;
247    /** recursion depth */
248    private int depth;
249    /** whether stream is closed */
250    private boolean closed;
251
252    /** wire handle -> obj/exception map */
253    private final HandleTable handles;
254    /** scratch field for passing handle values up/down call stack */
255    private int passHandle = NULL_HANDLE;
256    /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
257    private boolean defaultDataEnd = false;
258
259    /** buffer for reading primitive field values */
260    private byte[] primVals;
261
262    /** if true, invoke readObjectOverride() instead of readObject() */
263    private final boolean enableOverride;
264    /** if true, invoke resolveObject() */
265    private boolean enableResolve;
266
267    /**
268     * Context during upcalls to class-defined readObject methods; holds
269     * object currently being deserialized and descriptor for current class.
270     * Null when not during readObject upcall.
271     */
272    private SerialCallbackContext curContext;
273
274    /**
275     * Creates an ObjectInputStream that reads from the specified InputStream.
276     * A serialization stream header is read from the stream and verified.
277     * This constructor will block until the corresponding ObjectOutputStream
278     * has written and flushed the header.
279     *
280     * <p>If a security manager is installed, this constructor will check for
281     * the "enableSubclassImplementation" SerializablePermission when invoked
282     * directly or indirectly by the constructor of a subclass which overrides
283     * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
284     * methods.
285     *
286     * @param   in input stream to read from
287     * @throws  StreamCorruptedException if the stream header is incorrect
288     * @throws  IOException if an I/O error occurs while reading stream header
289     * @throws  SecurityException if untrusted subclass illegally overrides
290     *          security-sensitive methods
291     * @throws  NullPointerException if <code>in</code> is <code>null</code>
292     * @see     ObjectInputStream#ObjectInputStream()
293     * @see     ObjectInputStream#readFields()
294     * @see     ObjectOutputStream#ObjectOutputStream(OutputStream)
295     */
296    public ObjectInputStream(InputStream in) throws IOException {
297        verifySubclass();
298        bin = new BlockDataInputStream(in);
299        handles = new HandleTable(10);
300        vlist = new ValidationList();
301        enableOverride = false;
302        readStreamHeader();
303        bin.setBlockDataMode(true);
304    }
305
306    /**
307     * Provide a way for subclasses that are completely reimplementing
308     * ObjectInputStream to not have to allocate private data just used by this
309     * implementation of ObjectInputStream.
310     *
311     * <p>If there is a security manager installed, this method first calls the
312     * security manager's <code>checkPermission</code> method with the
313     * <code>SerializablePermission("enableSubclassImplementation")</code>
314     * permission to ensure it's ok to enable subclassing.
315     *
316     * @throws  SecurityException if a security manager exists and its
317     *          <code>checkPermission</code> method denies enabling
318     *          subclassing.
319     * @throws  IOException if an I/O error occurs while creating this stream
320     * @see SecurityManager#checkPermission
321     * @see java.io.SerializablePermission
322     */
323    protected ObjectInputStream() throws IOException, SecurityException {
324        SecurityManager sm = System.getSecurityManager();
325        if (sm != null) {
326            sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
327        }
328        bin = null;
329        handles = null;
330        vlist = null;
331        enableOverride = true;
332    }
333
334    /**
335     * Read an object from the ObjectInputStream.  The class of the object, the
336     * signature of the class, and the values of the non-transient and
337     * non-static fields of the class and all of its supertypes are read.
338     * Default deserializing for a class can be overriden using the writeObject
339     * and readObject methods.  Objects referenced by this object are read
340     * transitively so that a complete equivalent graph of objects is
341     * reconstructed by readObject.
342     *
343     * <p>The root object is completely restored when all of its fields and the
344     * objects it references are completely restored.  At this point the object
345     * validation callbacks are executed in order based on their registered
346     * priorities. The callbacks are registered by objects (in the readObject
347     * special methods) as they are individually restored.
348     *
349     * <p>Exceptions are thrown for problems with the InputStream and for
350     * classes that should not be deserialized.  All exceptions are fatal to
351     * the InputStream and leave it in an indeterminate state; it is up to the
352     * caller to ignore or recover the stream state.
353     *
354     * @throws  ClassNotFoundException Class of a serialized object cannot be
355     *          found.
356     * @throws  InvalidClassException Something is wrong with a class used by
357     *          serialization.
358     * @throws  StreamCorruptedException Control information in the
359     *          stream is inconsistent.
360     * @throws  OptionalDataException Primitive data was found in the
361     *          stream instead of objects.
362     * @throws  IOException Any of the usual Input/Output related exceptions.
363     */
364    public final Object readObject()
365        throws IOException, ClassNotFoundException
366    {
367        if (enableOverride) {
368            return readObjectOverride();
369        }
370
371        // if nested read, passHandle contains handle of enclosing object
372        int outerHandle = passHandle;
373        try {
374            Object obj = readObject0(false);
375            handles.markDependency(outerHandle, passHandle);
376            ClassNotFoundException ex = handles.lookupException(passHandle);
377            if (ex != null) {
378                throw ex;
379            }
380            if (depth == 0) {
381                vlist.doCallbacks();
382            }
383            return obj;
384        } finally {
385            passHandle = outerHandle;
386            if (closed && depth == 0) {
387                clear();
388            }
389        }
390    }
391
392    /**
393     * This method is called by trusted subclasses of ObjectOutputStream that
394     * constructed ObjectOutputStream using the protected no-arg constructor.
395     * The subclass is expected to provide an override method with the modifier
396     * "final".
397     *
398     * @return  the Object read from the stream.
399     * @throws  ClassNotFoundException Class definition of a serialized object
400     *          cannot be found.
401     * @throws  OptionalDataException Primitive data was found in the stream
402     *          instead of objects.
403     * @throws  IOException if I/O errors occurred while reading from the
404     *          underlying stream
405     * @see #ObjectInputStream()
406     * @see #readObject()
407     * @since 1.2
408     */
409    protected Object readObjectOverride()
410        throws IOException, ClassNotFoundException
411    {
412        return null;
413    }
414
415    /**
416     * Reads an "unshared" object from the ObjectInputStream.  This method is
417     * identical to readObject, except that it prevents subsequent calls to
418     * readObject and readUnshared from returning additional references to the
419     * deserialized instance obtained via this call.  Specifically:
420     * <ul>
421     *   <li>If readUnshared is called to deserialize a back-reference (the
422     *       stream representation of an object which has been written
423     *       previously to the stream), an ObjectStreamException will be
424     *       thrown.
425     *
426     *   <li>If readUnshared returns successfully, then any subsequent attempts
427     *       to deserialize back-references to the stream handle deserialized
428     *       by readUnshared will cause an ObjectStreamException to be thrown.
429     * </ul>
430     * Deserializing an object via readUnshared invalidates the stream handle
431     * associated with the returned object.  Note that this in itself does not
432     * always guarantee that the reference returned by readUnshared is unique;
433     * the deserialized object may define a readResolve method which returns an
434     * object visible to other parties, or readUnshared may return a Class
435     * object or enum constant obtainable elsewhere in the stream or through
436     * external means. If the deserialized object defines a readResolve method
437     * and the invocation of that method returns an array, then readUnshared
438     * returns a shallow clone of that array; this guarantees that the returned
439     * array object is unique and cannot be obtained a second time from an
440     * invocation of readObject or readUnshared on the ObjectInputStream,
441     * even if the underlying data stream has been manipulated.
442     *
443     * <p>ObjectInputStream subclasses which override this method can only be
444     * constructed in security contexts possessing the
445     * "enableSubclassImplementation" SerializablePermission; any attempt to
446     * instantiate such a subclass without this permission will cause a
447     * SecurityException to be thrown.
448     *
449     * @return  reference to deserialized object
450     * @throws  ClassNotFoundException if class of an object to deserialize
451     *          cannot be found
452     * @throws  StreamCorruptedException if control information in the stream
453     *          is inconsistent
454     * @throws  ObjectStreamException if object to deserialize has already
455     *          appeared in stream
456     * @throws  OptionalDataException if primitive data is next in stream
457     * @throws  IOException if an I/O error occurs during deserialization
458     * @since   1.4
459     */
460    public Object readUnshared() throws IOException, ClassNotFoundException {
461        // if nested read, passHandle contains handle of enclosing object
462        int outerHandle = passHandle;
463        try {
464            Object obj = readObject0(true);
465            handles.markDependency(outerHandle, passHandle);
466            ClassNotFoundException ex = handles.lookupException(passHandle);
467            if (ex != null) {
468                throw ex;
469            }
470            if (depth == 0) {
471                vlist.doCallbacks();
472            }
473            return obj;
474        } finally {
475            passHandle = outerHandle;
476            if (closed && depth == 0) {
477                clear();
478            }
479        }
480    }
481
482    /**
483     * Read the non-static and non-transient fields of the current class from
484     * this stream.  This may only be called from the readObject method of the
485     * class being deserialized. It will throw the NotActiveException if it is
486     * called otherwise.
487     *
488     * @throws  ClassNotFoundException if the class of a serialized object
489     *          could not be found.
490     * @throws  IOException if an I/O error occurs.
491     * @throws  NotActiveException if the stream is not currently reading
492     *          objects.
493     */
494    public void defaultReadObject()
495        throws IOException, ClassNotFoundException
496    {
497        SerialCallbackContext ctx = curContext;
498        if (ctx == null) {
499            throw new NotActiveException("not in call to readObject");
500        }
501        Object curObj = ctx.getObj();
502        ObjectStreamClass curDesc = ctx.getDesc();
503        bin.setBlockDataMode(false);
504        defaultReadFields(curObj, curDesc);
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        Object curObj = ctx.getObj();
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 static abstract 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<Boolean>() {
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 = null;
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        for (int i = 0; i < slots.length; i++) {
1890            ObjectStreamClass slotDesc = slots[i].desc;
1891
1892            if (slots[i].hasData) {
1893                if (obj == null || handles.lookupException(passHandle) != null) {
1894                    defaultReadFields(null, slotDesc); // skip field values
1895                } else if (slotDesc.hasReadObjectMethod()) {
1896                    SerialCallbackContext oldContext = curContext;
1897                    if (oldContext != null)
1898                        oldContext.check();
1899                    try {
1900                        curContext = new SerialCallbackContext(obj, slotDesc);
1901
1902                        bin.setBlockDataMode(true);
1903                        slotDesc.invokeReadObject(obj, this);
1904                    } catch (ClassNotFoundException ex) {
1905                        /*
1906                         * In most cases, the handle table has already
1907                         * propagated a CNFException to passHandle at this
1908                         * point; this mark call is included to address cases
1909                         * where the custom readObject method has cons'ed and
1910                         * thrown a new CNFException of its own.
1911                         */
1912                        handles.markException(passHandle, ex);
1913                    } finally {
1914                        curContext.setUsed();
1915                        if (oldContext!= null)
1916                            oldContext.check();
1917                        curContext = oldContext;
1918                    }
1919
1920                    /*
1921                     * defaultDataEnd may have been set indirectly by custom
1922                     * readObject() method when calling defaultReadObject() or
1923                     * readFields(); clear it to restore normal read behavior.
1924                     */
1925                    defaultDataEnd = false;
1926                } else {
1927                    defaultReadFields(obj, slotDesc);
1928                }
1929
1930                if (slotDesc.hasWriteObjectData()) {
1931                    skipCustomData();
1932                } else {
1933                    bin.setBlockDataMode(false);
1934                }
1935            } else {
1936                if (obj != null &&
1937                    slotDesc.hasReadObjectNoDataMethod() &&
1938                    handles.lookupException(passHandle) == null)
1939                {
1940                    slotDesc.invokeReadObjectNoData(obj);
1941                }
1942            }
1943        }
1944    }
1945
1946    /**
1947     * Skips over all block data and objects until TC_ENDBLOCKDATA is
1948     * encountered.
1949     */
1950    private void skipCustomData() throws IOException {
1951        int oldHandle = passHandle;
1952        for (;;) {
1953            if (bin.getBlockDataMode()) {
1954                bin.skipBlockData();
1955                bin.setBlockDataMode(false);
1956            }
1957            switch (bin.peekByte()) {
1958                case TC_BLOCKDATA:
1959                case TC_BLOCKDATALONG:
1960                    bin.setBlockDataMode(true);
1961                    break;
1962
1963                case TC_ENDBLOCKDATA:
1964                    bin.readByte();
1965                    passHandle = oldHandle;
1966                    return;
1967
1968                default:
1969                    readObject0(false);
1970                    break;
1971            }
1972        }
1973    }
1974
1975    /**
1976     * Reads in values of serializable fields declared by given class
1977     * descriptor.  If obj is non-null, sets field values in obj.  Expects that
1978     * passHandle is set to obj's handle before this method is called.
1979     */
1980    private void defaultReadFields(Object obj, ObjectStreamClass desc)
1981        throws IOException
1982    {
1983        Class<?> cl = desc.forClass();
1984        if (cl != null && obj != null && !cl.isInstance(obj)) {
1985            throw new ClassCastException();
1986        }
1987
1988        int primDataSize = desc.getPrimDataSize();
1989        if (primVals == null || primVals.length < primDataSize) {
1990            primVals = new byte[primDataSize];
1991        }
1992        bin.readFully(primVals, 0, primDataSize, false);
1993        if (obj != null) {
1994            desc.setPrimFieldValues(obj, primVals);
1995        }
1996
1997        int objHandle = passHandle;
1998        ObjectStreamField[] fields = desc.getFields(false);
1999        Object[] objVals = new Object[desc.getNumObjFields()];
2000        int numPrimFields = fields.length - objVals.length;
2001        for (int i = 0; i < objVals.length; i++) {
2002            ObjectStreamField f = fields[numPrimFields + i];
2003            objVals[i] = readObject0(f.isUnshared());
2004            if (f.getField() != null) {
2005                handles.markDependency(objHandle, passHandle);
2006            }
2007        }
2008        if (obj != null) {
2009            desc.setObjFieldValues(obj, objVals);
2010        }
2011        passHandle = objHandle;
2012    }
2013
2014    /**
2015     * Reads in and returns IOException that caused serialization to abort.
2016     * All stream state is discarded prior to reading in fatal exception.  Sets
2017     * passHandle to fatal exception's handle.
2018     */
2019    private IOException readFatalException() throws IOException {
2020        if (bin.readByte() != TC_EXCEPTION) {
2021            throw new InternalError();
2022        }
2023        clear();
2024        IOException e = (IOException) readObject0(false);
2025        // BEGIN Android-changed
2026        clear();
2027        // END Android-changed
2028        return e;
2029    }
2030
2031    /**
2032     * If recursion depth is 0, clears internal data structures; otherwise,
2033     * throws a StreamCorruptedException.  This method is called when a
2034     * TC_RESET typecode is encountered.
2035     */
2036    private void handleReset() throws StreamCorruptedException {
2037        if (depth > 0) {
2038            throw new StreamCorruptedException(
2039                "unexpected reset; recursion depth: " + depth);
2040        }
2041        clear();
2042    }
2043
2044    /**
2045     * Converts specified span of bytes into float values.
2046     */
2047    // REMIND: remove once hotspot inlines Float.intBitsToFloat
2048    private static native void bytesToFloats(byte[] src, int srcpos,
2049                                             float[] dst, int dstpos,
2050                                             int nfloats);
2051
2052    /**
2053     * Converts specified span of bytes into double values.
2054     */
2055    // REMIND: remove once hotspot inlines Double.longBitsToDouble
2056    private static native void bytesToDoubles(byte[] src, int srcpos,
2057                                              double[] dst, int dstpos,
2058                                              int ndoubles);
2059
2060    /**
2061     * Returns the first non-null class loader (not counting class loaders of
2062     * generated reflection implementation classes) up the execution stack, or
2063     * null if only code from the null class loader is on the stack.  This
2064     * method is also called via reflection by the following RMI-IIOP class:
2065     *
2066     *     com.sun.corba.se.internal.util.JDKClassLoader
2067     *
2068     * This method should not be removed or its signature changed without
2069     * corresponding modifications to the above class.
2070     */
2071    private static ClassLoader latestUserDefinedLoader() {
2072        return VMStack.getClosestUserClassLoader();
2073    }
2074
2075    /**
2076     * Default GetField implementation.
2077     */
2078    private class GetFieldImpl extends GetField {
2079
2080        /** class descriptor describing serializable fields */
2081        private final ObjectStreamClass desc;
2082        /** primitive field values */
2083        private final byte[] primVals;
2084        /** object field values */
2085        private final Object[] objVals;
2086        /** object field value handles */
2087        private final int[] objHandles;
2088
2089        /**
2090         * Creates GetFieldImpl object for reading fields defined in given
2091         * class descriptor.
2092         */
2093        GetFieldImpl(ObjectStreamClass desc) {
2094            this.desc = desc;
2095            primVals = new byte[desc.getPrimDataSize()];
2096            objVals = new Object[desc.getNumObjFields()];
2097            objHandles = new int[objVals.length];
2098        }
2099
2100        public ObjectStreamClass getObjectStreamClass() {
2101            return desc;
2102        }
2103
2104        public boolean defaulted(String name) throws IOException {
2105            return (getFieldOffset(name, null) < 0);
2106        }
2107
2108        public boolean get(String name, boolean val) throws IOException {
2109            int off = getFieldOffset(name, Boolean.TYPE);
2110            return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
2111        }
2112
2113        public byte get(String name, byte val) throws IOException {
2114            int off = getFieldOffset(name, Byte.TYPE);
2115            return (off >= 0) ? primVals[off] : val;
2116        }
2117
2118        public char get(String name, char val) throws IOException {
2119            int off = getFieldOffset(name, Character.TYPE);
2120            return (off >= 0) ? Bits.getChar(primVals, off) : val;
2121        }
2122
2123        public short get(String name, short val) throws IOException {
2124            int off = getFieldOffset(name, Short.TYPE);
2125            return (off >= 0) ? Bits.getShort(primVals, off) : val;
2126        }
2127
2128        public int get(String name, int val) throws IOException {
2129            int off = getFieldOffset(name, Integer.TYPE);
2130            return (off >= 0) ? Bits.getInt(primVals, off) : val;
2131        }
2132
2133        public float get(String name, float val) throws IOException {
2134            int off = getFieldOffset(name, Float.TYPE);
2135            return (off >= 0) ? Bits.getFloat(primVals, off) : val;
2136        }
2137
2138        public long get(String name, long val) throws IOException {
2139            int off = getFieldOffset(name, Long.TYPE);
2140            return (off >= 0) ? Bits.getLong(primVals, off) : val;
2141        }
2142
2143        public double get(String name, double val) throws IOException {
2144            int off = getFieldOffset(name, Double.TYPE);
2145            return (off >= 0) ? Bits.getDouble(primVals, off) : val;
2146        }
2147
2148        public Object get(String name, Object val) throws IOException {
2149            int off = getFieldOffset(name, Object.class);
2150            if (off >= 0) {
2151                int objHandle = objHandles[off];
2152                handles.markDependency(passHandle, objHandle);
2153                return (handles.lookupException(objHandle) == null) ?
2154                    objVals[off] : null;
2155            } else {
2156                return val;
2157            }
2158        }
2159
2160        /**
2161         * Reads primitive and object field values from stream.
2162         */
2163        void readFields() throws IOException {
2164            bin.readFully(primVals, 0, primVals.length, false);
2165
2166            int oldHandle = passHandle;
2167            ObjectStreamField[] fields = desc.getFields(false);
2168            int numPrimFields = fields.length - objVals.length;
2169            for (int i = 0; i < objVals.length; i++) {
2170                objVals[i] =
2171                    readObject0(fields[numPrimFields + i].isUnshared());
2172                objHandles[i] = passHandle;
2173            }
2174            passHandle = oldHandle;
2175        }
2176
2177        /**
2178         * Returns offset of field with given name and type.  A specified type
2179         * of null matches all types, Object.class matches all non-primitive
2180         * types, and any other non-null type matches assignable types only.
2181         * If no matching field is found in the (incoming) class
2182         * descriptor but a matching field is present in the associated local
2183         * class descriptor, returns -1.  Throws IllegalArgumentException if
2184         * neither incoming nor local class descriptor contains a match.
2185         */
2186        private int getFieldOffset(String name, Class<?> type) {
2187            ObjectStreamField field = desc.getField(name, type);
2188            if (field != null) {
2189                return field.getOffset();
2190            } else if (desc.getLocalDesc().getField(name, type) != null) {
2191                return -1;
2192            } else {
2193                throw new IllegalArgumentException("no such field " + name +
2194                                                   " with type " + type);
2195            }
2196        }
2197    }
2198
2199    /**
2200     * Prioritized list of callbacks to be performed once object graph has been
2201     * completely deserialized.
2202     */
2203    private static class ValidationList {
2204
2205        private static class Callback {
2206            final ObjectInputValidation obj;
2207            final int priority;
2208            Callback next;
2209            final AccessControlContext acc;
2210
2211            Callback(ObjectInputValidation obj, int priority, Callback next,
2212                AccessControlContext acc)
2213            {
2214                this.obj = obj;
2215                this.priority = priority;
2216                this.next = next;
2217                this.acc = acc;
2218            }
2219        }
2220
2221        /** linked list of callbacks */
2222        private Callback list;
2223
2224        /**
2225         * Creates new (empty) ValidationList.
2226         */
2227        ValidationList() {
2228        }
2229
2230        /**
2231         * Registers callback.  Throws InvalidObjectException if callback
2232         * object is null.
2233         */
2234        void register(ObjectInputValidation obj, int priority)
2235            throws InvalidObjectException
2236        {
2237            if (obj == null) {
2238                throw new InvalidObjectException("null callback");
2239            }
2240
2241            Callback prev = null, cur = list;
2242            while (cur != null && priority < cur.priority) {
2243                prev = cur;
2244                cur = cur.next;
2245            }
2246            AccessControlContext acc = AccessController.getContext();
2247            if (prev != null) {
2248                prev.next = new Callback(obj, priority, cur, acc);
2249            } else {
2250                list = new Callback(obj, priority, list, acc);
2251            }
2252        }
2253
2254        /**
2255         * Invokes all registered callbacks and clears the callback list.
2256         * Callbacks with higher priorities are called first; those with equal
2257         * priorities may be called in any order.  If any of the callbacks
2258         * throws an InvalidObjectException, the callback process is terminated
2259         * and the exception propagated upwards.
2260         */
2261        void doCallbacks() throws InvalidObjectException {
2262            try {
2263                while (list != null) {
2264                    AccessController.doPrivileged(
2265                        new PrivilegedExceptionAction<Void>()
2266                    {
2267                        public Void run() throws InvalidObjectException {
2268                            list.obj.validateObject();
2269                            return null;
2270                        }
2271                    }, list.acc);
2272                    list = list.next;
2273                }
2274            } catch (PrivilegedActionException ex) {
2275                list = null;
2276                throw (InvalidObjectException) ex.getException();
2277            }
2278        }
2279
2280        /**
2281         * Resets the callback list to its initial (empty) state.
2282         */
2283        public void clear() {
2284            list = null;
2285        }
2286    }
2287
2288    /**
2289     * Input stream supporting single-byte peek operations.
2290     */
2291    private static class PeekInputStream extends InputStream {
2292
2293        /** underlying stream */
2294        private final InputStream in;
2295        /** peeked byte */
2296        private int peekb = -1;
2297
2298        /**
2299         * Creates new PeekInputStream on top of given underlying stream.
2300         */
2301        PeekInputStream(InputStream in) {
2302            this.in = in;
2303        }
2304
2305        /**
2306         * Peeks at next byte value in stream.  Similar to read(), except
2307         * that it does not consume the read value.
2308         */
2309        int peek() throws IOException {
2310            return (peekb >= 0) ? peekb : (peekb = in.read());
2311        }
2312
2313        public int read() throws IOException {
2314            if (peekb >= 0) {
2315                int v = peekb;
2316                peekb = -1;
2317                return v;
2318            } else {
2319                return in.read();
2320            }
2321        }
2322
2323        public int read(byte[] b, int off, int len) throws IOException {
2324            if (len == 0) {
2325                return 0;
2326            } else if (peekb < 0) {
2327                return in.read(b, off, len);
2328            } else {
2329                b[off++] = (byte) peekb;
2330                len--;
2331                peekb = -1;
2332                int n = in.read(b, off, len);
2333                return (n >= 0) ? (n + 1) : 1;
2334            }
2335        }
2336
2337        void readFully(byte[] b, int off, int len) throws IOException {
2338            int n = 0;
2339            while (n < len) {
2340                int count = read(b, off + n, len - n);
2341                if (count < 0) {
2342                    throw new EOFException();
2343                }
2344                n += count;
2345            }
2346        }
2347
2348        public long skip(long n) throws IOException {
2349            if (n <= 0) {
2350                return 0;
2351            }
2352            int skipped = 0;
2353            if (peekb >= 0) {
2354                peekb = -1;
2355                skipped++;
2356                n--;
2357            }
2358            return skipped + skip(n);
2359        }
2360
2361        public int available() throws IOException {
2362            return in.available() + ((peekb >= 0) ? 1 : 0);
2363        }
2364
2365        public void close() throws IOException {
2366            in.close();
2367        }
2368    }
2369
2370    /**
2371     * Input stream with two modes: in default mode, inputs data written in the
2372     * same format as DataOutputStream; in "block data" mode, inputs data
2373     * bracketed by block data markers (see object serialization specification
2374     * for details).  Buffering depends on block data mode: when in default
2375     * mode, no data is buffered in advance; when in block data mode, all data
2376     * for the current data block is read in at once (and buffered).
2377     */
2378    private class BlockDataInputStream
2379        extends InputStream implements DataInput
2380    {
2381        /** maximum data block length */
2382        private static final int MAX_BLOCK_SIZE = 1024;
2383        /** maximum data block header length */
2384        private static final int MAX_HEADER_SIZE = 5;
2385        /** (tunable) length of char buffer (for reading strings) */
2386        private static final int CHAR_BUF_SIZE = 256;
2387        /** readBlockHeader() return value indicating header read may block */
2388        private static final int HEADER_BLOCKED = -2;
2389
2390        /** buffer for reading general/block data */
2391        private final byte[] buf = new byte[MAX_BLOCK_SIZE];
2392        /** buffer for reading block data headers */
2393        private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
2394        /** char buffer for fast string reads */
2395        private final char[] cbuf = new char[CHAR_BUF_SIZE];
2396
2397        /** block data mode */
2398        private boolean blkmode = false;
2399
2400        // block data state fields; values meaningful only when blkmode true
2401        /** current offset into buf */
2402        private int pos = 0;
2403        /** end offset of valid data in buf, or -1 if no more block data */
2404        private int end = -1;
2405        /** number of bytes in current block yet to be read from stream */
2406        private int unread = 0;
2407
2408        /** underlying stream (wrapped in peekable filter stream) */
2409        private final PeekInputStream in;
2410        /** loopback stream (for data reads that span data blocks) */
2411        private final DataInputStream din;
2412
2413        /**
2414         * Creates new BlockDataInputStream on top of given underlying stream.
2415         * Block data mode is turned off by default.
2416         */
2417        BlockDataInputStream(InputStream in) {
2418            this.in = new PeekInputStream(in);
2419            din = new DataInputStream(this);
2420        }
2421
2422        /**
2423         * Sets block data mode to the given mode (true == on, false == off)
2424         * and returns the previous mode value.  If the new mode is the same as
2425         * the old mode, no action is taken.  Throws IllegalStateException if
2426         * block data mode is being switched from on to off while unconsumed
2427         * block data is still present in the stream.
2428         */
2429        boolean setBlockDataMode(boolean newmode) throws IOException {
2430            if (blkmode == newmode) {
2431                return blkmode;
2432            }
2433            if (newmode) {
2434                pos = 0;
2435                end = 0;
2436                unread = 0;
2437            } else if (pos < end) {
2438                throw new IllegalStateException("unread block data");
2439            }
2440            blkmode = newmode;
2441            return !blkmode;
2442        }
2443
2444        /**
2445         * Returns true if the stream is currently in block data mode, false
2446         * otherwise.
2447         */
2448        boolean getBlockDataMode() {
2449            return blkmode;
2450        }
2451
2452        /**
2453         * If in block data mode, skips to the end of the current group of data
2454         * blocks (but does not unset block data mode).  If not in block data
2455         * mode, throws an IllegalStateException.
2456         */
2457        void skipBlockData() throws IOException {
2458            if (!blkmode) {
2459                throw new IllegalStateException("not in block data mode");
2460            }
2461            while (end >= 0) {
2462                refill();
2463            }
2464        }
2465
2466        /**
2467         * Attempts to read in the next block data header (if any).  If
2468         * canBlock is false and a full header cannot be read without possibly
2469         * blocking, returns HEADER_BLOCKED, else if the next element in the
2470         * stream is a block data header, returns the block data length
2471         * specified by the header, else returns -1.
2472         */
2473        private int readBlockHeader(boolean canBlock) throws IOException {
2474            if (defaultDataEnd) {
2475                /*
2476                 * Fix for 4360508: stream is currently at the end of a field
2477                 * value block written via default serialization; since there
2478                 * is no terminating TC_ENDBLOCKDATA tag, simulate
2479                 * end-of-custom-data behavior explicitly.
2480                 */
2481                return -1;
2482            }
2483            try {
2484                for (;;) {
2485                    int avail = canBlock ? Integer.MAX_VALUE : in.available();
2486                    if (avail == 0) {
2487                        return HEADER_BLOCKED;
2488                    }
2489
2490                    int tc = in.peek();
2491                    switch (tc) {
2492                        case TC_BLOCKDATA:
2493                            if (avail < 2) {
2494                                return HEADER_BLOCKED;
2495                            }
2496                            in.readFully(hbuf, 0, 2);
2497                            return hbuf[1] & 0xFF;
2498
2499                        case TC_BLOCKDATALONG:
2500                            if (avail < 5) {
2501                                return HEADER_BLOCKED;
2502                            }
2503                            in.readFully(hbuf, 0, 5);
2504                            int len = Bits.getInt(hbuf, 1);
2505                            if (len < 0) {
2506                                throw new StreamCorruptedException(
2507                                    "illegal block data header length: " +
2508                                    len);
2509                            }
2510                            return len;
2511
2512                        /*
2513                         * TC_RESETs may occur in between data blocks.
2514                         * Unfortunately, this case must be parsed at a lower
2515                         * level than other typecodes, since primitive data
2516                         * reads may span data blocks separated by a TC_RESET.
2517                         */
2518                        case TC_RESET:
2519                            in.read();
2520                            handleReset();
2521                            break;
2522
2523                        default:
2524                            if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
2525                                throw new StreamCorruptedException(
2526                                    String.format("invalid type code: %02X",
2527                                    tc));
2528                            }
2529                            return -1;
2530                    }
2531                }
2532            } catch (EOFException ex) {
2533                throw new StreamCorruptedException(
2534                    "unexpected EOF while reading block data header");
2535            }
2536        }
2537
2538        /**
2539         * Refills internal buffer buf with block data.  Any data in buf at the
2540         * time of the call is considered consumed.  Sets the pos, end, and
2541         * unread fields to reflect the new amount of available block data; if
2542         * the next element in the stream is not a data block, sets pos and
2543         * unread to 0 and end to -1.
2544         */
2545        private void refill() throws IOException {
2546            try {
2547                do {
2548                    pos = 0;
2549                    if (unread > 0) {
2550                        int n =
2551                            in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
2552                        if (n >= 0) {
2553                            end = n;
2554                            unread -= n;
2555                        } else {
2556                            throw new StreamCorruptedException(
2557                                "unexpected EOF in middle of data block");
2558                        }
2559                    } else {
2560                        int n = readBlockHeader(true);
2561                        if (n >= 0) {
2562                            end = 0;
2563                            unread = n;
2564                        } else {
2565                            end = -1;
2566                            unread = 0;
2567                        }
2568                    }
2569                } while (pos == end);
2570            } catch (IOException ex) {
2571                pos = 0;
2572                end = -1;
2573                unread = 0;
2574                throw ex;
2575            }
2576        }
2577
2578        /**
2579         * If in block data mode, returns the number of unconsumed bytes
2580         * remaining in the current data block.  If not in block data mode,
2581         * throws an IllegalStateException.
2582         */
2583        int currentBlockRemaining() {
2584            if (blkmode) {
2585                return (end >= 0) ? (end - pos) + unread : 0;
2586            } else {
2587                throw new IllegalStateException();
2588            }
2589        }
2590
2591        /**
2592         * Peeks at (but does not consume) and returns the next byte value in
2593         * the stream, or -1 if the end of the stream/block data (if in block
2594         * data mode) has been reached.
2595         */
2596        int peek() throws IOException {
2597            if (blkmode) {
2598                if (pos == end) {
2599                    refill();
2600                }
2601                return (end >= 0) ? (buf[pos] & 0xFF) : -1;
2602            } else {
2603                return in.peek();
2604            }
2605        }
2606
2607        /**
2608         * Peeks at (but does not consume) and returns the next byte value in
2609         * the stream, or throws EOFException if end of stream/block data has
2610         * been reached.
2611         */
2612        byte peekByte() throws IOException {
2613            int val = peek();
2614            if (val < 0) {
2615                throw new EOFException();
2616            }
2617            return (byte) val;
2618        }
2619
2620
2621        /* ----------------- generic input stream methods ------------------ */
2622        /*
2623         * The following methods are equivalent to their counterparts in
2624         * InputStream, except that they interpret data block boundaries and
2625         * read the requested data from within data blocks when in block data
2626         * mode.
2627         */
2628
2629        public int read() throws IOException {
2630            if (blkmode) {
2631                if (pos == end) {
2632                    refill();
2633                }
2634                return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
2635            } else {
2636                return in.read();
2637            }
2638        }
2639
2640        public int read(byte[] b, int off, int len) throws IOException {
2641            return read(b, off, len, false);
2642        }
2643
2644        public long skip(long len) throws IOException {
2645            long remain = len;
2646            while (remain > 0) {
2647                if (blkmode) {
2648                    if (pos == end) {
2649                        refill();
2650                    }
2651                    if (end < 0) {
2652                        break;
2653                    }
2654                    int nread = (int) Math.min(remain, end - pos);
2655                    remain -= nread;
2656                    pos += nread;
2657                } else {
2658                    int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
2659                    if ((nread = in.read(buf, 0, nread)) < 0) {
2660                        break;
2661                    }
2662                    remain -= nread;
2663                }
2664            }
2665            return len - remain;
2666        }
2667
2668        public int available() throws IOException {
2669            if (blkmode) {
2670                if ((pos == end) && (unread == 0)) {
2671                    int n;
2672                    while ((n = readBlockHeader(false)) == 0) ;
2673                    switch (n) {
2674                        case HEADER_BLOCKED:
2675                            break;
2676
2677                        case -1:
2678                            pos = 0;
2679                            end = -1;
2680                            break;
2681
2682                        default:
2683                            pos = 0;
2684                            end = 0;
2685                            unread = n;
2686                            break;
2687                    }
2688                }
2689                // avoid unnecessary call to in.available() if possible
2690                int unreadAvail = (unread > 0) ?
2691                    Math.min(in.available(), unread) : 0;
2692                return (end >= 0) ? (end - pos) + unreadAvail : 0;
2693            } else {
2694                return in.available();
2695            }
2696        }
2697
2698        public void close() throws IOException {
2699            if (blkmode) {
2700                pos = 0;
2701                end = -1;
2702                unread = 0;
2703            }
2704            in.close();
2705        }
2706
2707        /**
2708         * Attempts to read len bytes into byte array b at offset off.  Returns
2709         * the number of bytes read, or -1 if the end of stream/block data has
2710         * been reached.  If copy is true, reads values into an intermediate
2711         * buffer before copying them to b (to avoid exposing a reference to
2712         * b).
2713         */
2714        int read(byte[] b, int off, int len, boolean copy) throws IOException {
2715            if (len == 0) {
2716                return 0;
2717            } else if (blkmode) {
2718                if (pos == end) {
2719                    refill();
2720                }
2721                if (end < 0) {
2722                    return -1;
2723                }
2724                int nread = Math.min(len, end - pos);
2725                System.arraycopy(buf, pos, b, off, nread);
2726                pos += nread;
2727                return nread;
2728            } else if (copy) {
2729                int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
2730                if (nread > 0) {
2731                    System.arraycopy(buf, 0, b, off, nread);
2732                }
2733                return nread;
2734            } else {
2735                return in.read(b, off, len);
2736            }
2737        }
2738
2739        /* ----------------- primitive data input methods ------------------ */
2740        /*
2741         * The following methods are equivalent to their counterparts in
2742         * DataInputStream, except that they interpret data block boundaries
2743         * and read the requested data from within data blocks when in block
2744         * data mode.
2745         */
2746
2747        public void readFully(byte[] b) throws IOException {
2748            readFully(b, 0, b.length, false);
2749        }
2750
2751        public void readFully(byte[] b, int off, int len) throws IOException {
2752            readFully(b, off, len, false);
2753        }
2754
2755        public void readFully(byte[] b, int off, int len, boolean copy)
2756            throws IOException
2757        {
2758            while (len > 0) {
2759                int n = read(b, off, len, copy);
2760                if (n < 0) {
2761                    throw new EOFException();
2762                }
2763                off += n;
2764                len -= n;
2765            }
2766        }
2767
2768        public int skipBytes(int n) throws IOException {
2769            return din.skipBytes(n);
2770        }
2771
2772        public boolean readBoolean() throws IOException {
2773            int v = read();
2774            if (v < 0) {
2775                throw new EOFException();
2776            }
2777            return (v != 0);
2778        }
2779
2780        public byte readByte() throws IOException {
2781            int v = read();
2782            if (v < 0) {
2783                throw new EOFException();
2784            }
2785            return (byte) v;
2786        }
2787
2788        public int readUnsignedByte() throws IOException {
2789            int v = read();
2790            if (v < 0) {
2791                throw new EOFException();
2792            }
2793            return v;
2794        }
2795
2796        public char readChar() throws IOException {
2797            if (!blkmode) {
2798                pos = 0;
2799                in.readFully(buf, 0, 2);
2800            } else if (end - pos < 2) {
2801                return din.readChar();
2802            }
2803            char v = Bits.getChar(buf, pos);
2804            pos += 2;
2805            return v;
2806        }
2807
2808        public short readShort() throws IOException {
2809            if (!blkmode) {
2810                pos = 0;
2811                in.readFully(buf, 0, 2);
2812            } else if (end - pos < 2) {
2813                return din.readShort();
2814            }
2815            short v = Bits.getShort(buf, pos);
2816            pos += 2;
2817            return v;
2818        }
2819
2820        public int readUnsignedShort() throws IOException {
2821            if (!blkmode) {
2822                pos = 0;
2823                in.readFully(buf, 0, 2);
2824            } else if (end - pos < 2) {
2825                return din.readUnsignedShort();
2826            }
2827            int v = Bits.getShort(buf, pos) & 0xFFFF;
2828            pos += 2;
2829            return v;
2830        }
2831
2832        public int readInt() throws IOException {
2833            if (!blkmode) {
2834                pos = 0;
2835                in.readFully(buf, 0, 4);
2836            } else if (end - pos < 4) {
2837                return din.readInt();
2838            }
2839            int v = Bits.getInt(buf, pos);
2840            pos += 4;
2841            return v;
2842        }
2843
2844        public float readFloat() throws IOException {
2845            if (!blkmode) {
2846                pos = 0;
2847                in.readFully(buf, 0, 4);
2848            } else if (end - pos < 4) {
2849                return din.readFloat();
2850            }
2851            float v = Bits.getFloat(buf, pos);
2852            pos += 4;
2853            return v;
2854        }
2855
2856        public long readLong() throws IOException {
2857            if (!blkmode) {
2858                pos = 0;
2859                in.readFully(buf, 0, 8);
2860            } else if (end - pos < 8) {
2861                return din.readLong();
2862            }
2863            long v = Bits.getLong(buf, pos);
2864            pos += 8;
2865            return v;
2866        }
2867
2868        public double readDouble() throws IOException {
2869            if (!blkmode) {
2870                pos = 0;
2871                in.readFully(buf, 0, 8);
2872            } else if (end - pos < 8) {
2873                return din.readDouble();
2874            }
2875            double v = Bits.getDouble(buf, pos);
2876            pos += 8;
2877            return v;
2878        }
2879
2880        public String readUTF() throws IOException {
2881            return readUTFBody(readUnsignedShort());
2882        }
2883
2884        @SuppressWarnings("deprecation")
2885        public String readLine() throws IOException {
2886            return din.readLine();      // deprecated, not worth optimizing
2887        }
2888
2889        /* -------------- primitive data array input methods --------------- */
2890        /*
2891         * The following methods read in spans of primitive data values.
2892         * Though equivalent to calling the corresponding primitive read
2893         * methods repeatedly, these methods are optimized for reading groups
2894         * of primitive data values more efficiently.
2895         */
2896
2897        void readBooleans(boolean[] v, int off, int len) throws IOException {
2898            int stop, endoff = off + len;
2899            while (off < endoff) {
2900                if (!blkmode) {
2901                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
2902                    in.readFully(buf, 0, span);
2903                    stop = off + span;
2904                    pos = 0;
2905                } else if (end - pos < 1) {
2906                    v[off++] = din.readBoolean();
2907                    continue;
2908                } else {
2909                    stop = Math.min(endoff, off + end - pos);
2910                }
2911
2912                while (off < stop) {
2913                    v[off++] = Bits.getBoolean(buf, pos++);
2914                }
2915            }
2916        }
2917
2918        void readChars(char[] v, int off, int len) throws IOException {
2919            int stop, endoff = off + len;
2920            while (off < endoff) {
2921                if (!blkmode) {
2922                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
2923                    in.readFully(buf, 0, span << 1);
2924                    stop = off + span;
2925                    pos = 0;
2926                } else if (end - pos < 2) {
2927                    v[off++] = din.readChar();
2928                    continue;
2929                } else {
2930                    stop = Math.min(endoff, off + ((end - pos) >> 1));
2931                }
2932
2933                while (off < stop) {
2934                    v[off++] = Bits.getChar(buf, pos);
2935                    pos += 2;
2936                }
2937            }
2938        }
2939
2940        void readShorts(short[] v, int off, int len) throws IOException {
2941            int stop, endoff = off + len;
2942            while (off < endoff) {
2943                if (!blkmode) {
2944                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
2945                    in.readFully(buf, 0, span << 1);
2946                    stop = off + span;
2947                    pos = 0;
2948                } else if (end - pos < 2) {
2949                    v[off++] = din.readShort();
2950                    continue;
2951                } else {
2952                    stop = Math.min(endoff, off + ((end - pos) >> 1));
2953                }
2954
2955                while (off < stop) {
2956                    v[off++] = Bits.getShort(buf, pos);
2957                    pos += 2;
2958                }
2959            }
2960        }
2961
2962        void readInts(int[] v, int off, int len) throws IOException {
2963            int stop, endoff = off + len;
2964            while (off < endoff) {
2965                if (!blkmode) {
2966                    int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
2967                    in.readFully(buf, 0, span << 2);
2968                    stop = off + span;
2969                    pos = 0;
2970                } else if (end - pos < 4) {
2971                    v[off++] = din.readInt();
2972                    continue;
2973                } else {
2974                    stop = Math.min(endoff, off + ((end - pos) >> 2));
2975                }
2976
2977                while (off < stop) {
2978                    v[off++] = Bits.getInt(buf, pos);
2979                    pos += 4;
2980                }
2981            }
2982        }
2983
2984        void readFloats(float[] v, int off, int len) throws IOException {
2985            int span, endoff = off + len;
2986            while (off < endoff) {
2987                if (!blkmode) {
2988                    span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
2989                    in.readFully(buf, 0, span << 2);
2990                    pos = 0;
2991                } else if (end - pos < 4) {
2992                    v[off++] = din.readFloat();
2993                    continue;
2994                } else {
2995                    span = Math.min(endoff - off, ((end - pos) >> 2));
2996                }
2997
2998                bytesToFloats(buf, pos, v, off, span);
2999                off += span;
3000                pos += span << 2;
3001            }
3002        }
3003
3004        void readLongs(long[] 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 >> 3);
3009                    in.readFully(buf, 0, span << 3);
3010                    stop = off + span;
3011                    pos = 0;
3012                } else if (end - pos < 8) {
3013                    v[off++] = din.readLong();
3014                    continue;
3015                } else {
3016                    stop = Math.min(endoff, off + ((end - pos) >> 3));
3017                }
3018
3019                while (off < stop) {
3020                    v[off++] = Bits.getLong(buf, pos);
3021                    pos += 8;
3022                }
3023            }
3024        }
3025
3026        void readDoubles(double[] v, int off, int len) throws IOException {
3027            int span, endoff = off + len;
3028            while (off < endoff) {
3029                if (!blkmode) {
3030                    span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
3031                    in.readFully(buf, 0, span << 3);
3032                    pos = 0;
3033                } else if (end - pos < 8) {
3034                    v[off++] = din.readDouble();
3035                    continue;
3036                } else {
3037                    span = Math.min(endoff - off, ((end - pos) >> 3));
3038                }
3039
3040                bytesToDoubles(buf, pos, v, off, span);
3041                off += span;
3042                pos += span << 3;
3043            }
3044        }
3045
3046        /**
3047         * Reads in string written in "long" UTF format.  "Long" UTF format is
3048         * identical to standard UTF, except that it uses an 8 byte header
3049         * (instead of the standard 2 bytes) to convey the UTF encoding length.
3050         */
3051        String readLongUTF() throws IOException {
3052            return readUTFBody(readLong());
3053        }
3054
3055        /**
3056         * Reads in the "body" (i.e., the UTF representation minus the 2-byte
3057         * or 8-byte length header) of a UTF encoding, which occupies the next
3058         * utflen bytes.
3059         */
3060        private String readUTFBody(long utflen) throws IOException {
3061            StringBuilder sbuf = new StringBuilder();
3062            if (!blkmode) {
3063                end = pos = 0;
3064            }
3065
3066            while (utflen > 0) {
3067                int avail = end - pos;
3068                if (avail >= 3 || (long) avail == utflen) {
3069                    utflen -= readUTFSpan(sbuf, utflen);
3070                } else {
3071                    if (blkmode) {
3072                        // near block boundary, read one byte at a time
3073                        utflen -= readUTFChar(sbuf, utflen);
3074                    } else {
3075                        // shift and refill buffer manually
3076                        if (avail > 0) {
3077                            System.arraycopy(buf, pos, buf, 0, avail);
3078                        }
3079                        pos = 0;
3080                        end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
3081                        in.readFully(buf, avail, end - avail);
3082                    }
3083                }
3084            }
3085
3086            return sbuf.toString();
3087        }
3088
3089        /**
3090         * Reads span of UTF-encoded characters out of internal buffer
3091         * (starting at offset pos and ending at or before offset end),
3092         * consuming no more than utflen bytes.  Appends read characters to
3093         * sbuf.  Returns the number of bytes consumed.
3094         */
3095        private long readUTFSpan(StringBuilder sbuf, long utflen)
3096            throws IOException
3097        {
3098            int cpos = 0;
3099            int start = pos;
3100            int avail = Math.min(end - pos, CHAR_BUF_SIZE);
3101            // stop short of last char unless all of utf bytes in buffer
3102            int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
3103            boolean outOfBounds = false;
3104
3105            try {
3106                while (pos < stop) {
3107                    int b1, b2, b3;
3108                    b1 = buf[pos++] & 0xFF;
3109                    switch (b1 >> 4) {
3110                        case 0:
3111                        case 1:
3112                        case 2:
3113                        case 3:
3114                        case 4:
3115                        case 5:
3116                        case 6:
3117                        case 7:   // 1 byte format: 0xxxxxxx
3118                            cbuf[cpos++] = (char) b1;
3119                            break;
3120
3121                        case 12:
3122                        case 13:  // 2 byte format: 110xxxxx 10xxxxxx
3123                            b2 = buf[pos++];
3124                            if ((b2 & 0xC0) != 0x80) {
3125                                throw new UTFDataFormatException();
3126                            }
3127                            cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
3128                                                   ((b2 & 0x3F) << 0));
3129                            break;
3130
3131                        case 14:  // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
3132                            b3 = buf[pos + 1];
3133                            b2 = buf[pos + 0];
3134                            pos += 2;
3135                            if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
3136                                throw new UTFDataFormatException();
3137                            }
3138                            cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
3139                                                   ((b2 & 0x3F) << 6) |
3140                                                   ((b3 & 0x3F) << 0));
3141                            break;
3142
3143                        default:  // 10xx xxxx, 1111 xxxx
3144                            throw new UTFDataFormatException();
3145                    }
3146                }
3147            } catch (ArrayIndexOutOfBoundsException ex) {
3148                outOfBounds = true;
3149            } finally {
3150                if (outOfBounds || (pos - start) > utflen) {
3151                    /*
3152                     * Fix for 4450867: if a malformed utf char causes the
3153                     * conversion loop to scan past the expected end of the utf
3154                     * string, only consume the expected number of utf bytes.
3155                     */
3156                    pos = start + (int) utflen;
3157                    throw new UTFDataFormatException();
3158                }
3159            }
3160
3161            sbuf.append(cbuf, 0, cpos);
3162            return pos - start;
3163        }
3164
3165        /**
3166         * Reads in single UTF-encoded character one byte at a time, appends
3167         * the character to sbuf, and returns the number of bytes consumed.
3168         * This method is used when reading in UTF strings written in block
3169         * data mode to handle UTF-encoded characters which (potentially)
3170         * straddle block-data boundaries.
3171         */
3172        private int readUTFChar(StringBuilder sbuf, long utflen)
3173            throws IOException
3174        {
3175            int b1, b2, b3;
3176            b1 = readByte() & 0xFF;
3177            switch (b1 >> 4) {
3178                case 0:
3179                case 1:
3180                case 2:
3181                case 3:
3182                case 4:
3183                case 5:
3184                case 6:
3185                case 7:     // 1 byte format: 0xxxxxxx
3186                    sbuf.append((char) b1);
3187                    return 1;
3188
3189                case 12:
3190                case 13:    // 2 byte format: 110xxxxx 10xxxxxx
3191                    if (utflen < 2) {
3192                        throw new UTFDataFormatException();
3193                    }
3194                    b2 = readByte();
3195                    if ((b2 & 0xC0) != 0x80) {
3196                        throw new UTFDataFormatException();
3197                    }
3198                    sbuf.append((char) (((b1 & 0x1F) << 6) |
3199                                        ((b2 & 0x3F) << 0)));
3200                    return 2;
3201
3202                case 14:    // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
3203                    if (utflen < 3) {
3204                        if (utflen == 2) {
3205                            readByte();         // consume remaining byte
3206                        }
3207                        throw new UTFDataFormatException();
3208                    }
3209                    b2 = readByte();
3210                    b3 = readByte();
3211                    if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
3212                        throw new UTFDataFormatException();
3213                    }
3214                    sbuf.append((char) (((b1 & 0x0F) << 12) |
3215                                        ((b2 & 0x3F) << 6) |
3216                                        ((b3 & 0x3F) << 0)));
3217                    return 3;
3218
3219                default:   // 10xx xxxx, 1111 xxxx
3220                    throw new UTFDataFormatException();
3221            }
3222        }
3223    }
3224
3225    /**
3226     * Unsynchronized table which tracks wire handle to object mappings, as
3227     * well as ClassNotFoundExceptions associated with deserialized objects.
3228     * This class implements an exception-propagation algorithm for
3229     * determining which objects should have ClassNotFoundExceptions associated
3230     * with them, taking into account cycles and discontinuities (e.g., skipped
3231     * fields) in the object graph.
3232     *
3233     * <p>General use of the table is as follows: during deserialization, a
3234     * given object is first assigned a handle by calling the assign method.
3235     * This method leaves the assigned handle in an "open" state, wherein
3236     * dependencies on the exception status of other handles can be registered
3237     * by calling the markDependency method, or an exception can be directly
3238     * associated with the handle by calling markException.  When a handle is
3239     * tagged with an exception, the HandleTable assumes responsibility for
3240     * propagating the exception to any other objects which depend
3241     * (transitively) on the exception-tagged object.
3242     *
3243     * <p>Once all exception information/dependencies for the handle have been
3244     * registered, the handle should be "closed" by calling the finish method
3245     * on it.  The act of finishing a handle allows the exception propagation
3246     * algorithm to aggressively prune dependency links, lessening the
3247     * performance/memory impact of exception tracking.
3248     *
3249     * <p>Note that the exception propagation algorithm used depends on handles
3250     * being assigned/finished in LIFO order; however, for simplicity as well
3251     * as memory conservation, it does not enforce this constraint.
3252     */
3253    // REMIND: add full description of exception propagation algorithm?
3254    private static class HandleTable {
3255
3256        /* status codes indicating whether object has associated exception */
3257        private static final byte STATUS_OK = 1;
3258        private static final byte STATUS_UNKNOWN = 2;
3259        private static final byte STATUS_EXCEPTION = 3;
3260
3261        /** array mapping handle -> object status */
3262        byte[] status;
3263        /** array mapping handle -> object/exception (depending on status) */
3264        Object[] entries;
3265        /** array mapping handle -> list of dependent handles (if any) */
3266        HandleList[] deps;
3267        /** lowest unresolved dependency */
3268        int lowDep = -1;
3269        /** number of handles in table */
3270        int size = 0;
3271
3272        /**
3273         * Creates handle table with the given initial capacity.
3274         */
3275        HandleTable(int initialCapacity) {
3276            status = new byte[initialCapacity];
3277            entries = new Object[initialCapacity];
3278            deps = new HandleList[initialCapacity];
3279        }
3280
3281        /**
3282         * Assigns next available handle to given object, and returns assigned
3283         * handle.  Once object has been completely deserialized (and all
3284         * dependencies on other objects identified), the handle should be
3285         * "closed" by passing it to finish().
3286         */
3287        int assign(Object obj) {
3288            if (size >= entries.length) {
3289                grow();
3290            }
3291            status[size] = STATUS_UNKNOWN;
3292            entries[size] = obj;
3293            return size++;
3294        }
3295
3296        /**
3297         * Registers a dependency (in exception status) of one handle on
3298         * another.  The dependent handle must be "open" (i.e., assigned, but
3299         * not finished yet).  No action is taken if either dependent or target
3300         * handle is NULL_HANDLE.
3301         */
3302        void markDependency(int dependent, int target) {
3303            if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
3304                return;
3305            }
3306            switch (status[dependent]) {
3307
3308                case STATUS_UNKNOWN:
3309                    switch (status[target]) {
3310                        case STATUS_OK:
3311                            // ignore dependencies on objs with no exception
3312                            break;
3313
3314                        case STATUS_EXCEPTION:
3315                            // eagerly propagate exception
3316                            markException(dependent,
3317                                (ClassNotFoundException) entries[target]);
3318                            break;
3319
3320                        case STATUS_UNKNOWN:
3321                            // add to dependency list of target
3322                            if (deps[target] == null) {
3323                                deps[target] = new HandleList();
3324                            }
3325                            deps[target].add(dependent);
3326
3327                            // remember lowest unresolved target seen
3328                            if (lowDep < 0 || lowDep > target) {
3329                                lowDep = target;
3330                            }
3331                            break;
3332
3333                        default:
3334                            throw new InternalError();
3335                    }
3336                    break;
3337
3338                case STATUS_EXCEPTION:
3339                    break;
3340
3341                default:
3342                    throw new InternalError();
3343            }
3344        }
3345
3346        /**
3347         * Associates a ClassNotFoundException (if one not already associated)
3348         * with the currently active handle and propagates it to other
3349         * referencing objects as appropriate.  The specified handle must be
3350         * "open" (i.e., assigned, but not finished yet).
3351         */
3352        void markException(int handle, ClassNotFoundException ex) {
3353            switch (status[handle]) {
3354                case STATUS_UNKNOWN:
3355                    status[handle] = STATUS_EXCEPTION;
3356                    entries[handle] = ex;
3357
3358                    // propagate exception to dependents
3359                    HandleList dlist = deps[handle];
3360                    if (dlist != null) {
3361                        int ndeps = dlist.size();
3362                        for (int i = 0; i < ndeps; i++) {
3363                            markException(dlist.get(i), ex);
3364                        }
3365                        deps[handle] = null;
3366                    }
3367                    break;
3368
3369                case STATUS_EXCEPTION:
3370                    break;
3371
3372                default:
3373                    throw new InternalError();
3374            }
3375        }
3376
3377        /**
3378         * Marks given handle as finished, meaning that no new dependencies
3379         * will be marked for handle.  Calls to the assign and finish methods
3380         * must occur in LIFO order.
3381         */
3382        void finish(int handle) {
3383            int end;
3384            if (lowDep < 0) {
3385                // no pending unknowns, only resolve current handle
3386                end = handle + 1;
3387            } else if (lowDep >= handle) {
3388                // pending unknowns now clearable, resolve all upward handles
3389                end = size;
3390                lowDep = -1;
3391            } else {
3392                // unresolved backrefs present, can't resolve anything yet
3393                return;
3394            }
3395
3396            // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
3397            for (int i = handle; i < end; i++) {
3398                switch (status[i]) {
3399                    case STATUS_UNKNOWN:
3400                        status[i] = STATUS_OK;
3401                        deps[i] = null;
3402                        break;
3403
3404                    case STATUS_OK:
3405                    case STATUS_EXCEPTION:
3406                        break;
3407
3408                    default:
3409                        throw new InternalError();
3410                }
3411            }
3412        }
3413
3414        /**
3415         * Assigns a new object to the given handle.  The object previously
3416         * associated with the handle is forgotten.  This method has no effect
3417         * if the given handle already has an exception associated with it.
3418         * This method may be called at any time after the handle is assigned.
3419         */
3420        void setObject(int handle, Object obj) {
3421            switch (status[handle]) {
3422                case STATUS_UNKNOWN:
3423                case STATUS_OK:
3424                    entries[handle] = obj;
3425                    break;
3426
3427                case STATUS_EXCEPTION:
3428                    break;
3429
3430                default:
3431                    throw new InternalError();
3432            }
3433        }
3434
3435        /**
3436         * Looks up and returns object associated with the given handle.
3437         * Returns null if the given handle is NULL_HANDLE, or if it has an
3438         * associated ClassNotFoundException.
3439         */
3440        Object lookupObject(int handle) {
3441            return (handle != NULL_HANDLE &&
3442                    status[handle] != STATUS_EXCEPTION) ?
3443                entries[handle] : null;
3444        }
3445
3446        /**
3447         * Looks up and returns ClassNotFoundException associated with the
3448         * given handle.  Returns null if the given handle is NULL_HANDLE, or
3449         * if there is no ClassNotFoundException associated with the handle.
3450         */
3451        ClassNotFoundException lookupException(int handle) {
3452            return (handle != NULL_HANDLE &&
3453                    status[handle] == STATUS_EXCEPTION) ?
3454                (ClassNotFoundException) entries[handle] : null;
3455        }
3456
3457        /**
3458         * Resets table to its initial state.
3459         */
3460        void clear() {
3461            Arrays.fill(status, 0, size, (byte) 0);
3462            Arrays.fill(entries, 0, size, null);
3463            Arrays.fill(deps, 0, size, null);
3464            lowDep = -1;
3465            size = 0;
3466        }
3467
3468        /**
3469         * Returns number of handles registered in table.
3470         */
3471        int size() {
3472            return size;
3473        }
3474
3475        /**
3476         * Expands capacity of internal arrays.
3477         */
3478        private void grow() {
3479            int newCapacity = (entries.length << 1) + 1;
3480
3481            byte[] newStatus = new byte[newCapacity];
3482            Object[] newEntries = new Object[newCapacity];
3483            HandleList[] newDeps = new HandleList[newCapacity];
3484
3485            System.arraycopy(status, 0, newStatus, 0, size);
3486            System.arraycopy(entries, 0, newEntries, 0, size);
3487            System.arraycopy(deps, 0, newDeps, 0, size);
3488
3489            status = newStatus;
3490            entries = newEntries;
3491            deps = newDeps;
3492        }
3493
3494        /**
3495         * Simple growable list of (integer) handles.
3496         */
3497        private static class HandleList {
3498            private int[] list = new int[4];
3499            private int size = 0;
3500
3501            public HandleList() {
3502            }
3503
3504            public void add(int handle) {
3505                if (size >= list.length) {
3506                    int[] newList = new int[list.length << 1];
3507                    System.arraycopy(list, 0, newList, 0, list.length);
3508                    list = newList;
3509                }
3510                list[size++] = handle;
3511            }
3512
3513            public int get(int index) {
3514                if (index >= size) {
3515                    throw new ArrayIndexOutOfBoundsException();
3516                }
3517                return list[index];
3518            }
3519
3520            public int size() {
3521                return size;
3522            }
3523        }
3524    }
3525
3526    /**
3527     * Method for cloning arrays in case of using unsharing reading
3528     */
3529    private static Object cloneArray(Object array) {
3530        if (array instanceof Object[]) {
3531            return ((Object[]) array).clone();
3532        } else if (array instanceof boolean[]) {
3533            return ((boolean[]) array).clone();
3534        } else if (array instanceof byte[]) {
3535            return ((byte[]) array).clone();
3536        } else if (array instanceof char[]) {
3537            return ((char[]) array).clone();
3538        } else if (array instanceof double[]) {
3539            return ((double[]) array).clone();
3540        } else if (array instanceof float[]) {
3541            return ((float[]) array).clone();
3542        } else if (array instanceof int[]) {
3543            return ((int[]) array).clone();
3544        } else if (array instanceof long[]) {
3545            return ((long[]) array).clone();
3546        } else if (array instanceof short[]) {
3547            return ((short[]) array).clone();
3548        } else {
3549            throw new AssertionError();
3550        }
3551    }
3552
3553}
3554