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