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