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