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