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