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