1 /*
2  * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */

25
26 package java.io;
27
28 import java.io.ObjectStreamClass.WeakClassKey;
29 import java.lang.System.Logger;
30 import java.lang.ref.ReferenceQueue;
31 import java.lang.reflect.Array;
32 import java.lang.reflect.Modifier;
33 import java.lang.reflect.Proxy;
34 import java.security.AccessControlContext;
35 import java.security.AccessController;
36 import java.security.PrivilegedAction;
37 import java.security.PrivilegedActionException;
38 import java.security.PrivilegedExceptionAction;
39 import java.util.Arrays;
40 import java.util.Map;
41 import java.util.Objects;
42 import java.util.concurrent.ConcurrentHashMap;
43 import java.util.concurrent.ConcurrentMap;
44
45 import static java.io.ObjectStreamClass.processQueue;
46
47 import jdk.internal.misc.SharedSecrets;
48 import jdk.internal.misc.Unsafe;
49 import sun.reflect.misc.ReflectUtil;
50
51 /**
52  * An ObjectInputStream deserializes primitive data and objects previously
53  * written using an ObjectOutputStream.
54  *
55  * <p><strong>Warning: Deserialization of untrusted data is inherently dangerous
56  * and should be avoided. Untrusted data should be carefully validated according to the
57  * "Serialization and Deserialization" section of the
58  * {@extLink secure_coding_guidelines_javase Secure Coding Guidelines for Java SE}.
59  * {@extLink serialization_filter_guide Serialization Filtering} describes best
60  * practices for defensive use of serial filters.
61  * </strong></p>
62  *
63  * <p>ObjectOutputStream and ObjectInputStream can provide an application with
64  * persistent storage for graphs of objects when used with a FileOutputStream
65  * and FileInputStream respectively.  ObjectInputStream is used to recover
66  * those objects previously serialized. Other uses include passing objects
67  * between hosts using a socket stream or for marshaling and unmarshaling
68  * arguments and parameters in a remote communication system.
69  *
70  * <p>ObjectInputStream ensures that the types of all objects in the graph
71  * created from the stream match the classes present in the Java Virtual
72  * Machine.  Classes are loaded as required using the standard mechanisms.
73  *
74  * <p>Only objects that support the java.io.Serializable or
75  * java.io.Externalizable interface can be read from streams.
76  *
77  * <p>The method <code>readObject</code> is used to read an object from the
78  * stream.  Java's safe casting should be used to get the desired type.  In
79  * Java, strings and arrays are objects and are treated as objects during
80  * serialization. When read they need to be cast to the expected type.
81  *
82  * <p>Primitive data types can be read from the stream using the appropriate
83  * method on DataInput.
84  *
85  * <p>The default deserialization mechanism for objects restores the contents
86  * of each field to the value and type it had when it was written.  Fields
87  * declared as transient or static are ignored by the deserialization process.
88  * References to other objects cause those objects to be read from the stream
89  * as necessary.  Graphs of objects are restored correctly using a reference
90  * sharing mechanism.  New objects are always allocated when deserializing,
91  * which prevents existing objects from being overwritten.
92  *
93  * <p>Reading an object is analogous to running the constructors of a new
94  * object.  Memory is allocated for the object and initialized to zero (NULL).
95  * No-arg constructors are invoked for the non-serializable classes and then
96  * the fields of the serializable classes are restored from the stream starting
97  * with the serializable class closest to java.lang.object and finishing with
98  * the object's most specific class.
99  *
100  * <p>For example to read from a stream as written by the example in
101  * ObjectOutputStream:
102  * <br>
103  * <pre>
104  *      FileInputStream fis = new FileInputStream("t.tmp");
105  *      ObjectInputStream ois = new ObjectInputStream(fis);
106  *
107  *      int i = ois.readInt();
108  *      String today = (String) ois.readObject();
109  *      Date date = (Date) ois.readObject();
110  *
111  *      ois.close();
112  * </pre>
113  *
114  * <p>Classes control how they are serialized by implementing either the
115  * java.io.Serializable or java.io.Externalizable interfaces.
116  *
117  * <p>Implementing the Serializable interface allows object serialization to
118  * save and restore the entire state of the object and it allows classes to
119  * evolve between the time the stream is written and the time it is read.  It
120  * automatically traverses references between objects, saving and restoring
121  * entire graphs.
122  *
123  * <p>Serializable classes that require special handling during the
124  * serialization and deserialization process should implement the following
125  * methods:
126  *
127  * <pre>
128  * private void writeObject(java.io.ObjectOutputStream stream)
129  *     throws IOException;
130  * private void readObject(java.io.ObjectInputStream stream)
131  *     throws IOException, ClassNotFoundException;
132  * private void readObjectNoData()
133  *     throws ObjectStreamException;
134  * </pre>
135  *
136  * <p>The readObject method is responsible for reading and restoring the state
137  * of the object for its particular class using data written to the stream by
138  * the corresponding writeObject method.  The method does not need to concern
139  * itself with the state belonging to its superclasses or subclasses.  State is
140  * restored by reading data from the ObjectInputStream for the individual
141  * fields and making assignments to the appropriate fields of the object.
142  * Reading primitive data types is supported by DataInput.
143  *
144  * <p>Any attempt to read object data which exceeds the boundaries of the
145  * custom data written by the corresponding writeObject method will cause an
146  * OptionalDataException to be thrown with an eof field value of true.
147  * Non-object reads which exceed the end of the allotted data will reflect the
148  * end of data in the same way that they would indicate the end of the stream:
149  * bytewise reads will return -1 as the byte read or number of bytes read, and
150  * primitive reads will throw EOFExceptions.  If there is no corresponding
151  * writeObject method, then the end of default serialized data marks the end of
152  * the allotted data.
153  *
154  * <p>Primitive and object read calls issued from within a readExternal method
155  * behave in the same manner--if the stream is already positioned at the end of
156  * data written by the corresponding writeExternal method, object reads will
157  * throw OptionalDataExceptions with eof set to true, bytewise reads will
158  * return -1, and primitive reads will throw EOFExceptions.  Note that this
159  * behavior does not hold for streams written with the old
160  * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
161  * end of data written by writeExternal methods is not demarcated, and hence
162  * cannot be detected.
163  *
164  * <p>The readObjectNoData method is responsible for initializing the state of
165  * the object for its particular class in the event that the serialization
166  * stream does not list the given class as a superclass of the object being
167  * deserialized.  This may occur in cases where the receiving party uses a
168  * different version of the deserialized instance's class than the sending
169  * party, and the receiver's version extends classes that are not extended by
170  * the sender's version.  This may also occur if the serialization stream has
171  * been tampered; hence, readObjectNoData is useful for initializing
172  * deserialized objects properly despite a "hostile" or incomplete source
173  * stream.
174  *
175  * <p>Serialization does not read or assign values to the fields of any object
176  * that does not implement the java.io.Serializable interface.  Subclasses of
177  * Objects that are not serializable can be serializable. In this case the
178  * non-serializable class must have a no-arg constructor to allow its fields to
179  * be initialized.  In this case it is the responsibility of the subclass to
180  * save and restore the state of the non-serializable class. It is frequently
181  * the case that the fields of that class are accessible (publicpackage, or
182  * protected) or that there are get and set methods that can be used to restore
183  * the state.
184  *
185  * <p>The contents of the stream can be filtered during deserialization.
186  * If a {@linkplain #setObjectInputFilter(ObjectInputFilter) filter is set}
187  * on an ObjectInputStream, the {@link ObjectInputFilter} can check that
188  * the classes, array lengths, number of references in the stream, depth, and
189  * number of bytes consumed from the input stream are allowed and
190  * if not, can terminate deserialization.
191  * A {@linkplain ObjectInputFilter.Config#setSerialFilter(ObjectInputFilter) process-wide filter}
192  * can be configured that is applied to each {@code ObjectInputStream} unless replaced
193  * using {@link #setObjectInputFilter(ObjectInputFilter) setObjectInputFilter}.
194  *
195  * <p>Any exception that occurs while deserializing an object will be caught by
196  * the ObjectInputStream and abort the reading process.
197  *
198  * <p>Implementing the Externalizable interface allows the object to assume
199  * complete control over the contents and format of the object's serialized
200  * form.  The methods of the Externalizable interface, writeExternal and
201  * readExternal, are called to save and restore the objects state.  When
202  * implemented by a class they can write and read their own state using all of
203  * the methods of ObjectOutput and ObjectInput.  It is the responsibility of
204  * the objects to handle any versioning that occurs.
205  *
206  * <p>Enum constants are deserialized differently than ordinary serializable or
207  * externalizable objects.  The serialized form of an enum constant consists
208  * solely of its name; field values of the constant are not transmitted.  To
209  * deserialize an enum constant, ObjectInputStream reads the constant name from
210  * the stream; the deserialized constant is then obtained by calling the static
211  * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
212  * base type and the received constant name as arguments.  Like other
213  * serializable or externalizable objects, enum constants can function as the
214  * targets of back references appearing subsequently in the serialization
215  * stream.  The process by which enum constants are deserialized cannot be
216  * customized: any class-specific readObject, readObjectNoData, and readResolve
217  * methods defined by enum types are ignored during deserialization.
218  * Similarly, any serialPersistentFields or serialVersionUID field declarations
219  * are also ignored--all enum types have a fixed serialVersionUID of 0L.
220  *
221  * @author      Mike Warres
222  * @author      Roger Riggs
223  * @see java.io.DataInput
224  * @see java.io.ObjectOutputStream
225  * @see java.io.Serializable
226  * @see <a href="{@docRoot}/../specs/serialization/input.html">
227  *     Object Serialization Specification, Section 3, Object Input Classes</a>
228  * @since   1.1
229  */

230 public class ObjectInputStream
231     extends InputStream implements ObjectInput, ObjectStreamConstants
232 {
233     /** handle value representing null */
234     private static final int NULL_HANDLE = -1;
235
236     /** marker for unshared objects in internal handle table */
237     private static final Object unsharedMarker = new Object();
238
239     /**
240      * immutable table mapping primitive type names to corresponding
241      * class objects
242      */

243     private static final Map<String, Class<?>> primClasses =
244         Map.of("boolean"boolean.class,
245                "byte"byte.class,
246                "char"char.class,
247                "short"short.class,
248                "int"int.class,
249                "long"long.class,
250                "float"float.class,
251                "double"double.class,
252                "void"void.class);
253
254     private static class Caches {
255         /** cache of subclass security audit results */
256         static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
257             new ConcurrentHashMap<>();
258
259         /** queue for WeakReferences to audited subclasses */
260         static final ReferenceQueue<Class<?>> subclassAuditsQueue =
261             new ReferenceQueue<>();
262     }
263
264     /*
265      * Separate class to defer initialization of logging until needed.
266      */

267     private static class Logging {
268         /*
269          * Logger for ObjectInputFilter results.
270          * Setup the filter logger if it is set to DEBUG or TRACE.
271          * (Assuming it will not change).
272          */

273         static final System.Logger filterLogger;
274
275         static {
276             Logger filterLog = System.getLogger("java.io.serialization");
277             filterLogger = (filterLog.isLoggable(Logger.Level.DEBUG)
278                     || filterLog.isLoggable(Logger.Level.TRACE)) ? filterLog : null;
279         }
280     }
281
282     /** filter stream for handling block data conversion */
283     private final BlockDataInputStream bin;
284     /** validation callback list */
285     private final ValidationList vlist;
286     /** recursion depth */
287     private long depth;
288     /** Total number of references to any type of object, classenum, proxy, etc. */
289     private long totalObjectRefs;
290     /** whether stream is closed */
291     private boolean closed;
292
293     /** wire handle -> obj/exception map */
294     private final HandleTable handles;
295     /** scratch field for passing handle values up/down call stack */
296     private int passHandle = NULL_HANDLE;
297     /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
298     private boolean defaultDataEnd = false;
299
300     /** if true, invoke readObjectOverride() instead of readObject() */
301     private final boolean enableOverride;
302     /** if true, invoke resolveObject() */
303     private boolean enableResolve;
304
305     /**
306      * Context during upcalls to class-defined readObject methods; holds
307      * object currently being deserialized and descriptor for current class.
308      * Null when not during readObject upcall.
309      */

310     private SerialCallbackContext curContext;
311
312     /**
313      * Filter of class descriptors and classes read from the stream;
314      * may be null.
315      */

316     private ObjectInputFilter serialFilter;
317
318     /**
319      * Creates an ObjectInputStream that reads from the specified InputStream.
320      * A serialization stream header is read from the stream and verified.
321      * This constructor will block until the corresponding ObjectOutputStream
322      * has written and flushed the header.
323      *
324      * <p>The serialization filter is initialized to the value of
325      * {@linkplain ObjectInputFilter.Config#getSerialFilter() the process-wide filter}.
326      *
327      * <p>If a security manager is installed, this constructor will check for
328      * the "enableSubclassImplementation" SerializablePermission when invoked
329      * directly or indirectly by the constructor of a subclass which overrides
330      * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
331      * methods.
332      *
333      * @param   in input stream to read from
334      * @throws  StreamCorruptedException if the stream header is incorrect
335      * @throws  IOException if an I/O error occurs while reading stream header
336      * @throws  SecurityException if untrusted subclass illegally overrides
337      *          security-sensitive methods
338      * @throws  NullPointerException if <code>in</code> is <code>null</code>
339      * @see     ObjectInputStream#ObjectInputStream()
340      * @see     ObjectInputStream#readFields()
341      * @see     ObjectOutputStream#ObjectOutputStream(OutputStream)
342      */

343     public ObjectInputStream(InputStream in) throws IOException {
344         verifySubclass();
345         bin = new BlockDataInputStream(in);
346         handles = new HandleTable(10);
347         vlist = new ValidationList();
348         serialFilter = ObjectInputFilter.Config.getSerialFilter();
349         enableOverride = false;
350         readStreamHeader();
351         bin.setBlockDataMode(true);
352     }
353
354     /**
355      * Provide a way for subclasses that are completely reimplementing
356      * ObjectInputStream to not have to allocate private data just used by this
357      * implementation of ObjectInputStream.
358      *
359      * <p>The serialization filter is initialized to the value of
360      * {@linkplain ObjectInputFilter.Config#getSerialFilter() the process-wide filter}.
361      *
362      * <p>If there is a security manager installed, this method first calls the
363      * security manager's <code>checkPermission</code> method with the
364      * <code>SerializablePermission("enableSubclassImplementation")</code>
365      * permission to ensure it's ok to enable subclassing.
366      *
367      * @throws  SecurityException if a security manager exists and its
368      *          <code>checkPermission</code> method denies enabling
369      *          subclassing.
370      * @throws  IOException if an I/O error occurs while creating this stream
371      * @see SecurityManager#checkPermission
372      * @see java.io.SerializablePermission
373      */

374     protected ObjectInputStream() throws IOException, SecurityException {
375         SecurityManager sm = System.getSecurityManager();
376         if (sm != null) {
377             sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
378         }
379         bin = null;
380         handles = null;
381         vlist = null;
382         serialFilter = ObjectInputFilter.Config.getSerialFilter();
383         enableOverride = true;
384     }
385
386     /**
387      * Read an object from the ObjectInputStream.  The class of the object, the
388      * signature of the class, and the values of the non-transient and
389      * non-static fields of the class and all of its supertypes are read.
390      * Default deserializing for a class can be overridden using the writeObject
391      * and readObject methods.  Objects referenced by this object are read
392      * transitively so that a complete equivalent graph of objects is
393      * reconstructed by readObject.
394      *
395      * <p>The root object is completely restored when all of its fields and the
396      * objects it references are completely restored.  At this point the object
397      * validation callbacks are executed in order based on their registered
398      * priorities. The callbacks are registered by objects (in the readObject
399      * special methods) as they are individually restored.
400      *
401      * <p>The serialization filter, when not {@code null}, is invoked for
402      * each object (regular or class) read to reconstruct the root object.
403      * See {@link #setObjectInputFilter(ObjectInputFilter) setObjectInputFilter} for details.
404      *
405      * <p>Exceptions are thrown for problems with the InputStream and for
406      * classes that should not be deserialized.  All exceptions are fatal to
407      * the InputStream and leave it in an indeterminate state; it is up to the
408      * caller to ignore or recover the stream state.
409      *
410      * @throws  ClassNotFoundException Class of a serialized object cannot be
411      *          found.
412      * @throws  InvalidClassException Something is wrong with a class used by
413      *          serialization.
414      * @throws  StreamCorruptedException Control information in the
415      *          stream is inconsistent.
416      * @throws  OptionalDataException Primitive data was found in the
417      *          stream instead of objects.
418      * @throws  IOException Any of the usual Input/Output related exceptions.
419      */

420     public final Object readObject()
421         throws IOException, ClassNotFoundException {
422         return readObject(Object.class);
423     }
424
425     /**
426      * Reads a String and only a string.
427      *
428      * @return  the String read
429      * @throws  EOFException If end of file is reached.
430      * @throws  IOException If other I/O error has occurred.
431      */

432     private String readString() throws IOException {
433         try {
434             return (String) readObject(String.class);
435         } catch (ClassNotFoundException cnf) {
436             throw new IllegalStateException(cnf);
437         }
438     }
439
440     /**
441      * Internal method to read an object from the ObjectInputStream of the expected type.
442      * Called only from {@code readObject()} and {@code readString()}.
443      * Only {@code Object.class} and {@code String.class} are supported.
444      *
445      * @param type the type expected; either Object.class or String.class
446      * @return an object of the type
447      * @throws  IOException Any of the usual Input/Output related exceptions.
448      * @throws  ClassNotFoundException Class of a serialized object cannot be
449      *          found.
450      */

451     private final Object readObject(Class<?> type)
452         throws IOException, ClassNotFoundException
453     {
454         if (enableOverride) {
455             return readObjectOverride();
456         }
457
458         if (! (type == Object.class || type == String.class))
459             throw new AssertionError("internal error");
460
461         // if nested read, passHandle contains handle of enclosing object
462         int outerHandle = passHandle;
463         try {
464             Object obj = readObject0(type, false);
465             handles.markDependency(outerHandle, passHandle);
466             ClassNotFoundException ex = handles.lookupException(passHandle);
467             if (ex != null) {
468                 throw ex;
469             }
470             if (depth == 0) {
471                 vlist.doCallbacks();
472                 freeze();
473             }
474             return obj;
475         } finally {
476             passHandle = outerHandle;
477             if (closed && depth == 0) {
478                 clear();
479             }
480         }
481     }
482
483     /**
484      * This method is called by trusted subclasses of ObjectOutputStream that
485      * constructed ObjectOutputStream using the protected no-arg constructor.
486      * The subclass is expected to provide an override method with the modifier
487      * "final".
488      *
489      * @return  the Object read from the stream.
490      * @throws  ClassNotFoundException Class definition of a serialized object
491      *          cannot be found.
492      * @throws  OptionalDataException Primitive data was found in the stream
493      *          instead of objects.
494      * @throws  IOException if I/O errors occurred while reading from the
495      *          underlying stream
496      * @see #ObjectInputStream()
497      * @see #readObject()
498      * @since 1.2
499      */

500     protected Object readObjectOverride()
501         throws IOException, ClassNotFoundException
502     {
503         return null;
504     }
505
506     /**
507      * Reads an "unshared" object from the ObjectInputStream.  This method is
508      * identical to readObject, except that it prevents subsequent calls to
509      * readObject and readUnshared from returning additional references to the
510      * deserialized instance obtained via this call.  Specifically:
511      * <ul>
512      *   <li>If readUnshared is called to deserialize a back-reference (the
513      *       stream representation of an object which has been written
514      *       previously to the stream), an ObjectStreamException will be
515      *       thrown.
516      *
517      *   <li>If readUnshared returns successfully, then any subsequent attempts
518      *       to deserialize back-references to the stream handle deserialized
519      *       by readUnshared will cause an ObjectStreamException to be thrown.
520      * </ul>
521      * Deserializing an object via readUnshared invalidates the stream handle
522      * associated with the returned object.  Note that this in itself does not
523      * always guarantee that the reference returned by readUnshared is unique;
524      * the deserialized object may define a readResolve method which returns an
525      * object visible to other parties, or readUnshared may return a Class
526      * object or enum constant obtainable elsewhere in the stream or through
527      * external means. If the deserialized object defines a readResolve method
528      * and the invocation of that method returns an array, then readUnshared
529      * returns a shallow clone of that array; this guarantees that the returned
530      * array object is unique and cannot be obtained a second time from an
531      * invocation of readObject or readUnshared on the ObjectInputStream,
532      * even if the underlying data stream has been manipulated.
533      *
534      * <p>The serialization filter, when not {@code null}, is invoked for
535      * each object (regular or class) read to reconstruct the root object.
536      * See {@link #setObjectInputFilter(ObjectInputFilter) setObjectInputFilter} for details.
537      *
538      * <p>ObjectInputStream subclasses which override this method can only be
539      * constructed in security contexts possessing the
540      * "enableSubclassImplementation" SerializablePermission; any attempt to
541      * instantiate such a subclass without this permission will cause a
542      * SecurityException to be thrown.
543      *
544      * @return  reference to deserialized object
545      * @throws  ClassNotFoundException if class of an object to deserialize
546      *          cannot be found
547      * @throws  StreamCorruptedException if control information in the stream
548      *          is inconsistent
549      * @throws  ObjectStreamException if object to deserialize has already
550      *          appeared in stream
551      * @throws  OptionalDataException if primitive data is next in stream
552      * @throws  IOException if an I/O error occurs during deserialization
553      * @since   1.4
554      */

555     public Object readUnshared() throws IOException, ClassNotFoundException {
556         // if nested read, passHandle contains handle of enclosing object
557         int outerHandle = passHandle;
558         try {
559             Object obj = readObject0(Object.classtrue);
560             handles.markDependency(outerHandle, passHandle);
561             ClassNotFoundException ex = handles.lookupException(passHandle);
562             if (ex != null) {
563                 throw ex;
564             }
565             if (depth == 0) {
566                 vlist.doCallbacks();
567                 freeze();
568             }
569             return obj;
570         } finally {
571             passHandle = outerHandle;
572             if (closed && depth == 0) {
573                 clear();
574             }
575         }
576     }
577
578     /**
579      * Read the non-static and non-transient fields of the current class from
580      * this stream.  This may only be called from the readObject method of the
581      * class being deserialized. It will throw the NotActiveException if it is
582      * called otherwise.
583      *
584      * @throws  ClassNotFoundException if the class of a serialized object
585      *          could not be found.
586      * @throws  IOException if an I/O error occurs.
587      * @throws  NotActiveException if the stream is not currently reading
588      *          objects.
589      */

590     public void defaultReadObject()
591         throws IOException, ClassNotFoundException
592     {
593         SerialCallbackContext ctx = curContext;
594         if (ctx == null) {
595             throw new NotActiveException("not in call to readObject");
596         }
597         Object curObj = ctx.getObj();
598         ObjectStreamClass curDesc = ctx.getDesc();
599         bin.setBlockDataMode(false);
600         FieldValues vals = defaultReadFields(curObj, curDesc);
601         if (curObj != null) {
602             defaultCheckFieldValues(curObj, curDesc, vals);
603             defaultSetFieldValues(curObj, curDesc, vals);
604         }
605         bin.setBlockDataMode(true);
606         if (!curDesc.hasWriteObjectData()) {
607             /*
608              * Fix for 4360508: since stream does not contain terminating
609              * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
610              * knows to simulate end-of-custom-data behavior.
611              */

612             defaultDataEnd = true;
613         }
614         ClassNotFoundException ex = handles.lookupException(passHandle);
615         if (ex != null) {
616             throw ex;
617         }
618     }
619
620     /**
621      * Reads the persistent fields from the stream and makes them available by
622      * name.
623      *
624      * @return  the <code>GetField</code> object representing the persistent
625      *          fields of the object being deserialized
626      * @throws  ClassNotFoundException if the class of a serialized object
627      *          could not be found.
628      * @throws  IOException if an I/O error occurs.
629      * @throws  NotActiveException if the stream is not currently reading
630      *          objects.
631      * @since 1.2
632      */

633     public ObjectInputStream.GetField readFields()
634         throws IOException, ClassNotFoundException
635     {
636         SerialCallbackContext ctx = curContext;
637         if (ctx == null) {
638             throw new NotActiveException("not in call to readObject");
639         }
640         ctx.checkAndSetUsed();
641         ObjectStreamClass curDesc = ctx.getDesc();
642         bin.setBlockDataMode(false);
643         GetFieldImpl getField = new GetFieldImpl(curDesc);
644         getField.readFields();
645         bin.setBlockDataMode(true);
646         if (!curDesc.hasWriteObjectData()) {
647             /*
648              * Fix for 4360508: since stream does not contain terminating
649              * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
650              * knows to simulate end-of-custom-data behavior.
651              */

652             defaultDataEnd = true;
653         }
654
655         return getField;
656     }
657
658     /**
659      * Register an object to be validated before the graph is returned.  While
660      * similar to resolveObject these validations are called after the entire
661      * graph has been reconstituted.  Typically, a readObject method will
662      * register the object with the stream so that when all of the objects are
663      * restored a final set of validations can be performed.
664      *
665      * @param   obj the object to receive the validation callback.
666      * @param   prio controls the order of callbacks;zero is a good default.
667      *          Use higher numbers to be called back earlier, lower numbers for
668      *          later callbacks. Within a priority, callbacks are processed in
669      *          no particular order.
670      * @throws  NotActiveException The stream is not currently reading objects
671      *          so it is invalid to register a callback.
672      * @throws  InvalidObjectException The validation object is null.
673      */

674     public void registerValidation(ObjectInputValidation obj, int prio)
675         throws NotActiveException, InvalidObjectException
676     {
677         if (depth == 0) {
678             throw new NotActiveException("stream inactive");
679         }
680         vlist.register(obj, prio);
681     }
682
683     /**
684      * Load the local class equivalent of the specified stream class
685      * description.  Subclasses may implement this method to allow classes to
686      * be fetched from an alternate source.
687      *
688      * <p>The corresponding method in <code>ObjectOutputStream</code> is
689      * <code>annotateClass</code>.  This method will be invoked only once for
690      * each unique class in the stream.  This method can be implemented by
691      * subclasses to use an alternate loading mechanism but must return a
692      * <code>Class</code> object. Once returned, if the class is not an array
693      * class, its serialVersionUID is compared to the serialVersionUID of the
694      * serialized class, and if there is a mismatch, the deserialization fails
695      * and an {@link InvalidClassException} is thrown.
696      *
697      * <p>The default implementation of this method in
698      * <code>ObjectInputStream</code> returns the result of calling
699      * <pre>
700      *     Class.forName(desc.getName(), false, loader)
701      * </pre>
702      * where <code>loader</code> is the first class loader on the current
703      * thread's stack (starting from the currently executing method) that is
704      * neither the {@linkplain ClassLoader#getPlatformClassLoader() platform
705      * class loader} nor its ancestor; otherwise, <code>loader</code> is the
706      * <em>platform class loader</em>. If this call results in a
707      * <code>ClassNotFoundException</code> and the name of the passed
708      * <code>ObjectStreamClass</code> instance is the Java language keyword
709      * for a primitive type or void, then the <code>Class</code> object
710      * representing that primitive type or void will be returned
711      * (e.g., an <code>ObjectStreamClass</code> with the name
712      * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
713      * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
714      * the caller of this method.
715      *
716      * @param   desc an instance of class <code>ObjectStreamClass</code>
717      * @return  a <code>Class</code> object corresponding to <code>desc</code>
718      * @throws  IOException any of the usual Input/Output exceptions.
719      * @throws  ClassNotFoundException if class of a serialized object cannot
720      *          be found.
721      */

722     protected Class<?> resolveClass(ObjectStreamClass desc)
723         throws IOException, ClassNotFoundException
724     {
725         String name = desc.getName();
726         try {
727             return Class.forName(name, false, latestUserDefinedLoader());
728         } catch (ClassNotFoundException ex) {
729             Class<?> cl = primClasses.get(name);
730             if (cl != null) {
731                 return cl;
732             } else {
733                 throw ex;
734             }
735         }
736     }
737
738     /**
739      * Returns a proxy class that implements the interfaces named in a proxy
740      * class descriptor; subclasses may implement this method to read custom
741      * data from the stream along with the descriptors for dynamic proxy
742      * classes, allowing them to use an alternate loading mechanism for the
743      * interfaces and the proxy class.
744      *
745      * <p>This method is called exactly once for each unique proxy class
746      * descriptor in the stream.
747      *
748      * <p>The corresponding method in <code>ObjectOutputStream</code> is
749      * <code>annotateProxyClass</code>.  For a given subclass of
750      * <code>ObjectInputStream</code> that overrides this method, the
751      * <code>annotateProxyClass</code> method in the corresponding subclass of
752      * <code>ObjectOutputStream</code> must write any data or objects read by
753      * this method.
754      *
755      * <p>The default implementation of this method in
756      * <code>ObjectInputStream</code> returns the result of calling
757      * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
758      * objects for the interfaces that are named in the <code>interfaces</code>
759      * parameter.  The <code>Class</code> object for each interface name
760      * <code>i</code> is the value returned by calling
761      * <pre>
762      *     Class.forName(i, false, loader)
763      * </pre>
764      * where <code>loader</code> is the first class loader on the current
765      * thread's stack (starting from the currently executing method) that is
766      * neither the {@linkplain ClassLoader#getPlatformClassLoader() platform
767      * class loader} nor its ancestor; otherwise, <code>loader</code> is the
768      * <em>platform class loader</em>.
769      * Unless any of the resolved interfaces are non-publicthis same value
770      * of <code>loader</code> is also the class loader passed to
771      * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
772      * their class loader is passed instead (if more than one non-public
773      * interface class loader is encountered, an
774      * <code>IllegalAccessError</code> is thrown).
775      * If <code>Proxy.getProxyClass</code> throws an
776      * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
777      * will throw a <code>ClassNotFoundException</code> containing the
778      * <code>IllegalArgumentException</code>.
779      *
780      * @param interfaces the list of interface names that were
781      *                deserialized in the proxy class descriptor
782      * @return  a proxy class for the specified interfaces
783      * @throws        IOException any exception thrown by the underlying
784      *                <code>InputStream</code>
785      * @throws        ClassNotFoundException if the proxy class or any of the
786      *                named interfaces could not be found
787      * @see ObjectOutputStream#annotateProxyClass(Class)
788      * @since 1.3
789      */

790     protected Class<?> resolveProxyClass(String[] interfaces)
791         throws IOException, ClassNotFoundException
792     {
793         ClassLoader latestLoader = latestUserDefinedLoader();
794         ClassLoader nonPublicLoader = null;
795         boolean hasNonPublicInterface = false;
796
797         // define proxy in class loader of non-public interface(s), if any
798         Class<?>[] classObjs = new Class<?>[interfaces.length];
799         for (int i = 0; i < interfaces.length; i++) {
800             Class<?> cl = Class.forName(interfaces[i], false, latestLoader);
801             if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
802                 if (hasNonPublicInterface) {
803                     if (nonPublicLoader != cl.getClassLoader()) {
804                         throw new IllegalAccessError(
805                             "conflicting non-public interface class loaders");
806                     }
807                 } else {
808                     nonPublicLoader = cl.getClassLoader();
809                     hasNonPublicInterface = true;
810                 }
811             }
812             classObjs[i] = cl;
813         }
814         try {
815             @SuppressWarnings("deprecation")
816             Class<?> proxyClass = Proxy.getProxyClass(
817                 hasNonPublicInterface ? nonPublicLoader : latestLoader,
818                 classObjs);
819             return proxyClass;
820         } catch (IllegalArgumentException e) {
821             throw new ClassNotFoundException(null, e);
822         }
823     }
824
825     /**
826      * This method will allow trusted subclasses of ObjectInputStream to
827      * substitute one object for another during deserialization. Replacing
828      * objects is disabled until enableResolveObject is called. The
829      * enableResolveObject method checks that the stream requesting to resolve
830      * object can be trusted. Every reference to serializable objects is passed
831      * to resolveObject.  To insure that the private state of objects is not
832      * unintentionally exposed only trusted streams may use resolveObject.
833      *
834      * <p>This method is called after an object has been read but before it is
835      * returned from readObject.  The default resolveObject method just returns
836      * the same object.
837      *
838      * <p>When a subclass is replacing objects it must insure that the
839      * substituted object is compatible with every field where the reference
840      * will be stored.  Objects whose type is not a subclass of the type of the
841      * field or array element abort the serialization by raising an exception
842      * and the object is not be stored.
843      *
844      * <p>This method is called only once when each object is first
845      * encountered.  All subsequent references to the object will be redirected
846      * to the new object.
847      *
848      * @param   obj object to be substituted
849      * @return  the substituted object
850      * @throws  IOException Any of the usual Input/Output exceptions.
851      */

852     protected Object resolveObject(Object obj) throws IOException {
853         return obj;
854     }
855
856     /**
857      * Enables the stream to do replacement of objects read from the stream. When
858      * enabled, the {@link #resolveObject} method is called for every object being
859      * deserialized.
860      *
861      * <p>If object replacement is currently not enabled, and
862      * {@code enable} is true, and there is a security manager installed,
863      * this method first calls the security manager's
864      * {@code checkPermission} method with the
865      * {@code SerializablePermission("enableSubstitution")} permission to
866      * ensure that the caller is permitted to enable the stream to do replacement
867      * of objects read from the stream.
868      *
869      * @param   enable true for enabling use of {@code resolveObject} for
870      *          every object being deserialized
871      * @return  the previous setting before this method was invoked
872      * @throws  SecurityException if a security manager exists and its
873      *          {@code checkPermission} method denies enabling the stream
874      *          to do replacement of objects read from the stream.
875      * @see SecurityManager#checkPermission
876      * @see java.io.SerializablePermission
877      */

878     protected boolean enableResolveObject(boolean enable)
879         throws SecurityException
880     {
881         if (enable == enableResolve) {
882             return enable;
883         }
884         if (enable) {
885             SecurityManager sm = System.getSecurityManager();
886             if (sm != null) {
887                 sm.checkPermission(SUBSTITUTION_PERMISSION);
888             }
889         }
890         enableResolve = enable;
891         return !enableResolve;
892     }
893
894     /**
895      * The readStreamHeader method is provided to allow subclasses to read and
896      * verify their own stream headers. It reads and verifies the magic number
897      * and version number.
898      *
899      * @throws  IOException if there are I/O errors while reading from the
900      *          underlying <code>InputStream</code>
901      * @throws  StreamCorruptedException if control information in the stream
902      *          is inconsistent
903      */

904     protected void readStreamHeader()
905         throws IOException, StreamCorruptedException
906     {
907         short s0 = bin.readShort();
908         short s1 = bin.readShort();
909         if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
910             throw new StreamCorruptedException(
911                 String.format("invalid stream header: %04X%04X", s0, s1));
912         }
913     }
914
915     /**
916      * Read a class descriptor from the serialization stream.  This method is
917      * called when the ObjectInputStream expects a class descriptor as the next
918      * item in the serialization stream.  Subclasses of ObjectInputStream may
919      * override this method to read in class descriptors that have been written
920      * in non-standard formats (by subclasses of ObjectOutputStream which have
921      * overridden the <code>writeClassDescriptor</code> method).  By default,
922      * this method reads class descriptors according to the format defined in
923      * the Object Serialization specification.
924      *
925      * @return  the class descriptor read
926      * @throws  IOException If an I/O error has occurred.
927      * @throws  ClassNotFoundException If the Class of a serialized object used
928      *          in the class descriptor representation cannot be found
929      * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
930      * @since 1.3
931      */

932     protected ObjectStreamClass readClassDescriptor()
933         throws IOException, ClassNotFoundException
934     {
935         ObjectStreamClass desc = new ObjectStreamClass();
936         desc.readNonProxy(this);
937         return desc;
938     }
939
940     /**
941      * Reads a byte of data. This method will block if no input is available.
942      *
943      * @return  the byte read, or -1 if the end of the stream is reached.
944      * @throws  IOException If an I/O error has occurred.
945      */

946     public int read() throws IOException {
947         return bin.read();
948     }
949
950     /**
951      * Reads into an array of bytes.  This method will block until some input
952      * is available. Consider using java.io.DataInputStream.readFully to read
953      * exactly 'length' bytes.
954      *
955      * @param   buf the buffer into which the data is read
956      * @param   off the start offset in the destination array {@code buf}
957      * @param   len the maximum number of bytes read
958      * @return  the actual number of bytes read, -1 is returned when the end of
959      *          the stream is reached.
960      * @throws  NullPointerException if {@code buf} is {@code null}.
961      * @throws  IndexOutOfBoundsException if {@code off} is negative,
962      *          {@code len} is negative, or {@code len} is greater than
963      *          {@code buf.length - off}.
964      * @throws  IOException If an I/O error has occurred.
965      * @see java.io.DataInputStream#readFully(byte[],int,int)
966      */

967     public int read(byte[] buf, int off, int len) throws IOException {
968         if (buf == null) {
969             throw new NullPointerException();
970         }
971         int endoff = off + len;
972         if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
973             throw new IndexOutOfBoundsException();
974         }
975         return bin.read(buf, off, len, false);
976     }
977
978     /**
979      * Returns the number of bytes that can be read without blocking.
980      *
981      * @return  the number of available bytes.
982      * @throws  IOException if there are I/O errors while reading from the
983      *          underlying <code>InputStream</code>
984      */

985     public int available() throws IOException {
986         return bin.available();
987     }
988
989     /**
990      * Closes the input stream. Must be called to release any resources
991      * associated with the stream.
992      *
993      * @throws  IOException If an I/O error has occurred.
994      */

995     public void close() throws IOException {
996         /*
997          * Even if stream already closed, propagate redundant close to
998          * underlying stream to stay consistent with previous implementations.
999          */

1000         closed = true;
1001         if (depth == 0) {
1002             clear();
1003         }
1004         bin.close();
1005     }
1006
1007     /**
1008      * Reads in a boolean.
1009      *
1010      * @return  the boolean read.
1011      * @throws  EOFException If end of file is reached.
1012      * @throws  IOException If other I/O error has occurred.
1013      */

1014     public boolean readBoolean() throws IOException {
1015         return bin.readBoolean();
1016     }
1017
1018     /**
1019      * Reads an 8 bit byte.
1020      *
1021      * @return  the 8 bit byte read.
1022      * @throws  EOFException If end of file is reached.
1023      * @throws  IOException If other I/O error has occurred.
1024      */

1025     public byte readByte() throws IOException  {
1026         return bin.readByte();
1027     }
1028
1029     /**
1030      * Reads an unsigned 8 bit byte.
1031      *
1032      * @return  the 8 bit byte read.
1033      * @throws  EOFException If end of file is reached.
1034      * @throws  IOException If other I/O error has occurred.
1035      */

1036     public int readUnsignedByte()  throws IOException {
1037         return bin.readUnsignedByte();
1038     }
1039
1040     /**
1041      * Reads a 16 bit char.
1042      *
1043      * @return  the 16 bit char read.
1044      * @throws  EOFException If end of file is reached.
1045      * @throws  IOException If other I/O error has occurred.
1046      */

1047     public char readChar()  throws IOException {
1048         return bin.readChar();
1049     }
1050
1051     /**
1052      * Reads a 16 bit short.
1053      *
1054      * @return  the 16 bit short read.
1055      * @throws  EOFException If end of file is reached.
1056      * @throws  IOException If other I/O error has occurred.
1057      */

1058     public short readShort()  throws IOException {
1059         return bin.readShort();
1060     }
1061
1062     /**
1063      * Reads an unsigned 16 bit short.
1064      *
1065      * @return  the 16 bit short read.
1066      * @throws  EOFException If end of file is reached.
1067      * @throws  IOException If other I/O error has occurred.
1068      */

1069     public int readUnsignedShort() throws IOException {
1070         return bin.readUnsignedShort();
1071     }
1072
1073     /**
1074      * Reads a 32 bit int.
1075      *
1076      * @return  the 32 bit integer read.
1077      * @throws  EOFException If end of file is reached.
1078      * @throws  IOException If other I/O error has occurred.
1079      */

1080     public int readInt()  throws IOException {
1081         return bin.readInt();
1082     }
1083
1084     /**
1085      * Reads a 64 bit long.
1086      *
1087      * @return  the read 64 bit long.
1088      * @throws  EOFException If end of file is reached.
1089      * @throws  IOException If other I/O error has occurred.
1090      */

1091     public long readLong()  throws IOException {
1092         return bin.readLong();
1093     }
1094
1095     /**
1096      * Reads a 32 bit float.
1097      *
1098      * @return  the 32 bit float read.
1099      * @throws  EOFException If end of file is reached.
1100      * @throws  IOException If other I/O error has occurred.
1101      */

1102     public float readFloat() throws IOException {
1103         return bin.readFloat();
1104     }
1105
1106     /**
1107      * Reads a 64 bit double.
1108      *
1109      * @return  the 64 bit double read.
1110      * @throws  EOFException If end of file is reached.
1111      * @throws  IOException If other I/O error has occurred.
1112      */

1113     public double readDouble() throws IOException {
1114         return bin.readDouble();
1115     }
1116
1117     /**
1118      * Reads bytes, blocking until all bytes are read.
1119      *
1120      * @param   buf the buffer into which the data is read
1121      * @throws  NullPointerException If {@code buf} is {@code null}.
1122      * @throws  EOFException If end of file is reached.
1123      * @throws  IOException If other I/O error has occurred.
1124      */

1125     public void readFully(byte[] buf) throws IOException {
1126         bin.readFully(buf, 0, buf.length, false);
1127     }
1128
1129     /**
1130      * Reads bytes, blocking until all bytes are read.
1131      *
1132      * @param   buf the buffer into which the data is read
1133      * @param   off the start offset into the data array {@code buf}
1134      * @param   len the maximum number of bytes to read
1135      * @throws  NullPointerException If {@code buf} is {@code null}.
1136      * @throws  IndexOutOfBoundsException If {@code off} is negative,
1137      *          {@code len} is negative, or {@code len} is greater than
1138      *          {@code buf.length - off}.
1139      * @throws  EOFException If end of file is reached.
1140      * @throws  IOException If other I/O error has occurred.
1141      */

1142     public void readFully(byte[] buf, int off, int len) throws IOException {
1143         int endoff = off + len;
1144         if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
1145             throw new IndexOutOfBoundsException();
1146         }
1147         bin.readFully(buf, off, len, false);
1148     }
1149
1150     /**
1151      * Skips bytes.
1152      *
1153      * @param   len the number of bytes to be skipped
1154      * @return  the actual number of bytes skipped.
1155      * @throws  IOException If an I/O error has occurred.
1156      */

1157     public int skipBytes(int len) throws IOException {
1158         return bin.skipBytes(len);
1159     }
1160
1161     /**
1162      * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
1163      *
1164      * @return  a String copy of the line.
1165      * @throws  IOException if there are I/O errors while reading from the
1166      *          underlying <code>InputStream</code>
1167      * @deprecated This method does not properly convert bytes to characters.
1168      *          see DataInputStream for the details and alternatives.
1169      */

1170     @Deprecated
1171     public String readLine() throws IOException {
1172         return bin.readLine();
1173     }
1174
1175     /**
1176      * Reads a String in
1177      * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
1178      * format.
1179      *
1180      * @return  the String.
1181      * @throws  IOException if there are I/O errors while reading from the
1182      *          underlying <code>InputStream</code>
1183      * @throws  UTFDataFormatException if read bytes do not represent a valid
1184      *          modified UTF-8 encoding of a string
1185      */

1186     public String readUTF() throws IOException {
1187         return bin.readUTF();
1188     }
1189
1190     /**
1191      * Returns the serialization filter for this stream.
1192      * The serialization filter is the most recent filter set in
1193      * {@link #setObjectInputFilter setObjectInputFilter} or
1194      * the initial process-wide filter from
1195      * {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}.
1196      *
1197      * @return the serialization filter for the stream; may be null
1198      * @since 9
1199      */

1200     public final ObjectInputFilter getObjectInputFilter() {
1201         return serialFilter;
1202     }
1203
1204     /**
1205      * Set the serialization filter for the stream.
1206      * The filter's {@link ObjectInputFilter#checkInput checkInput} method is called
1207      * for each class and reference in the stream.
1208      * The filter can check any or all of the class, the array length, the number
1209      * of references, the depth of the graph, and the size of the input stream.
1210      * The depth is the number of nested {@linkplain #readObject readObject}
1211      * calls starting with the reading of the root of the graph being deserialized
1212      * and the current object being deserialized.
1213      * The number of references is the cumulative number of objects and references
1214      * to objects already read from the stream including the current object being read.
1215      * The filter is invoked only when reading objects from the stream and for
1216      * not primitives.
1217      * <p>
1218      * If the filter returns {@link ObjectInputFilter.Status#REJECTED Status.REJECTED},
1219      * {@code null} or throws a {@link RuntimeException},
1220      * the active {@code readObject} or {@code readUnshared}
1221      * throws {@link InvalidClassException}, otherwise deserialization
1222      * continues uninterrupted.
1223      * <p>
1224      * The serialization filter is initialized to the value of
1225      * {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}
1226      * when the {@code  ObjectInputStream} is constructed and can be set
1227      * to a custom filter only once.
1228      *
1229      * @implSpec
1230      * The filter, when not {@code null}, is invoked during {@link #readObject readObject}
1231      * and {@link #readUnshared readUnshared} for each object (regular or class) in the stream.
1232      * Strings are treated as primitives and do not invoke the filter.
1233      * The filter is called for:
1234      * <ul>
1235      *     <li>each object reference previously deserialized from the stream
1236      *     (class is {@code null}, arrayLength is -1),
1237      *     <li>each regular class (class is not {@code null}, arrayLength is -1),
1238      *     <li>each interface of a dynamic proxy and the dynamic proxy class itself
1239      *     (class is not {@code null}, arrayLength is -1),
1240      *     <li>each array is filtered using the array type and length of the array
1241      *     (class is the array type, arrayLength is the requested length),
1242      *     <li>each object replaced by its class' {@code readResolve} method
1243      *         is filtered using the replacement object's classif not {@code null},
1244      *         and if it is an array, the arrayLength, otherwise -1,
1245      *     <li>and each object replaced by {@link #resolveObject resolveObject}
1246      *         is filtered using the replacement object's classif not {@code null},
1247      *         and if it is an array, the arrayLength, otherwise -1.
1248      * </ul>
1249      *
1250      * When the {@link ObjectInputFilter#checkInput checkInput} method is invoked
1251      * it is given access to the current class, the array length,
1252      * the current number of references already read from the stream,
1253      * the depth of nested calls to {@link #readObject readObject} or
1254      * {@link #readUnshared readUnshared},
1255      * and the implementation dependent number of bytes consumed from the input stream.
1256      * <p>
1257      * Each call to {@link #readObject readObject} or
1258      * {@link #readUnshared readUnshared} increases the depth by 1
1259      * before reading an object and decreases by 1 before returning
1260      * normally or exceptionally.
1261      * The depth starts at {@code 1} and increases for each nested object and
1262      * decrements when each nested call returns.
1263      * The count of references in the stream starts at {@code 1} and
1264      * is increased before reading an object.
1265      *
1266      * @param filter the filter, may be null
1267      * @throws SecurityException if there is security manager and the
1268      *       {@code SerializablePermission("serialFilter")} is not granted
1269      * @throws IllegalStateException if the {@linkplain #getObjectInputFilter() current filter}
1270      *       is not {@code null} and is not the process-wide filter
1271      * @since 9
1272      */

1273     public final void setObjectInputFilter(ObjectInputFilter filter) {
1274         SecurityManager sm = System.getSecurityManager();
1275         if (sm != null) {
1276             sm.checkPermission(ObjectStreamConstants.SERIAL_FILTER_PERMISSION);
1277         }
1278         // Allow replacement of the process-wide filter if not already set
1279         if (serialFilter != null &&
1280                 serialFilter != ObjectInputFilter.Config.getSerialFilter()) {
1281             throw new IllegalStateException("filter can not be set more than once");
1282         }
1283         this.serialFilter = filter;
1284     }
1285
1286     /**
1287      * Invoke the serialization filter if non-null.
1288      * If the filter rejects or an exception is thrown, throws InvalidClassException.
1289      *
1290      * @param clazz the class; may be null
1291      * @param arrayLength the array length requested; use {@code -1} if not creating an array
1292      * @throws InvalidClassException if it rejected by the filter or
1293      *        a {@link RuntimeException} is thrown
1294      */

1295     private void filterCheck(Class<?> clazz, int arrayLength)
1296             throws InvalidClassException {
1297         if (serialFilter != null) {
1298             RuntimeException ex = null;
1299             ObjectInputFilter.Status status;
1300             // Info about the stream is not available if overridden by subclass, return 0
1301             long bytesRead = (bin == null) ? 0 : bin.getBytesRead();
1302             try {
1303                 status = serialFilter.checkInput(new FilterValues(clazz, arrayLength,
1304                         totalObjectRefs, depth, bytesRead));
1305             } catch (RuntimeException e) {
1306                 // Preventive interception of an exception to log
1307                 status = ObjectInputFilter.Status.REJECTED;
1308                 ex = e;
1309             }
1310             if (Logging.filterLogger != null) {
1311                 // Debug logging of filter checks that fail; Tracing for those that succeed
1312                 Logging.filterLogger.log(status == null || status == ObjectInputFilter.Status.REJECTED
1313                                 ? Logger.Level.DEBUG
1314                                 : Logger.Level.TRACE,
1315                         "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
1316                         status, clazz, arrayLength, totalObjectRefs, depth, bytesRead,
1317                         Objects.toString(ex, "n/a"));
1318             }
1319             if (status == null ||
1320                     status == ObjectInputFilter.Status.REJECTED) {
1321                 InvalidClassException ice = new InvalidClassException("filter status: " + status);
1322                 ice.initCause(ex);
1323                 throw ice;
1324             }
1325         }
1326     }
1327
1328     /**
1329      * Checks the given array type and length to ensure that creation of such
1330      * an array is permitted by this ObjectInputStream. The arrayType argument
1331      * must represent an actual array type.
1332      *
1333      * This private method is called via SharedSecrets.
1334      *
1335      * @param arrayType the array type
1336      * @param arrayLength the array length
1337      * @throws NullPointerException if arrayType is null
1338      * @throws IllegalArgumentException if arrayType isn't actually an array type
1339      * @throws NegativeArraySizeException if arrayLength is negative
1340      * @throws InvalidClassException if the filter rejects creation
1341      */

1342     private void checkArray(Class<?> arrayType, int arrayLength) throws InvalidClassException {
1343         if (! arrayType.isArray()) {
1344             throw new IllegalArgumentException("not an array type");
1345         }
1346
1347         if (arrayLength < 0) {
1348             throw new NegativeArraySizeException();
1349         }
1350
1351         filterCheck(arrayType, arrayLength);
1352     }
1353
1354     /**
1355      * Provide access to the persistent fields read from the input stream.
1356      */

1357     public abstract static class GetField {
1358
1359         /**
1360          * Get the ObjectStreamClass that describes the fields in the stream.
1361          *
1362          * @return  the descriptor class that describes the serializable fields
1363          */

1364         public abstract ObjectStreamClass getObjectStreamClass();
1365
1366         /**
1367          * Return true if the named field is defaulted and has no value in this
1368          * stream.
1369          *
1370          * @param  name the name of the field
1371          * @return trueif and only if the named field is defaulted
1372          * @throws IOException if there are I/O errors while reading from
1373          *         the underlying <code>InputStream</code>
1374          * @throws IllegalArgumentException if <code>name</code> does not
1375          *         correspond to a serializable field
1376          */

1377         public abstract boolean defaulted(String name) throws IOException;
1378
1379         /**
1380          * Get the value of the named boolean field from the persistent field.
1381          *
1382          * @param  name the name of the field
1383          * @param  val the default value to use if <code>name</code> does not
1384          *         have a value
1385          * @return the value of the named <code>boolean</code> field
1386          * @throws IOException if there are I/O errors while reading from the
1387          *         underlying <code>InputStream</code>
1388          * @throws IllegalArgumentException if type of <code>name</code> is
1389          *         not serializable or if the field type is incorrect
1390          */

1391         public abstract boolean get(String name, boolean val)
1392             throws IOException;
1393
1394         /**
1395          * Get the value of the named byte field from the persistent field.
1396          *
1397          * @param  name the name of the field
1398          * @param  val the default value to use if <code>name</code> does not
1399          *         have a value
1400          * @return the value of the named <code>byte</code> field
1401          * @throws IOException if there are I/O errors while reading from the
1402          *         underlying <code>InputStream</code>
1403          * @throws IllegalArgumentException if type of <code>name</code> is
1404          *         not serializable or if the field type is incorrect
1405          */

1406         public abstract byte get(String name, byte val) throws IOException;
1407
1408         /**
1409          * Get the value of the named char field from the persistent field.
1410          *
1411          * @param  name the name of the field
1412          * @param  val the default value to use if <code>name</code> does not
1413          *         have a value
1414          * @return the value of the named <code>char</code> field
1415          * @throws IOException if there are I/O errors while reading from the
1416          *         underlying <code>InputStream</code>
1417          * @throws IllegalArgumentException if type of <code>name</code> is
1418          *         not serializable or if the field type is incorrect
1419          */

1420         public abstract char get(String name, char val) throws IOException;
1421
1422         /**
1423          * Get the value of the named short 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</code> does not
1427          *         have a value
1428          * @return the value of the named <code>short</code> field
1429          * @throws IOException if there are I/O errors while reading from the
1430          *         underlying <code>InputStream</code>
1431          * @throws IllegalArgumentException if type of <code>name</code> is
1432          *         not serializable or if the field type is incorrect
1433          */

1434         public abstract short get(String name, short val) throws IOException;
1435
1436         /**
1437          * Get the value of the named int field from the persistent field.
1438          *
1439          * @param  name the name of the field
1440          * @param  val the default value to use if <code>name</code> does not
1441          *         have a value
1442          * @return the value of the named <code>int</code> field
1443          * @throws IOException if there are I/O errors while reading from the
1444          *         underlying <code>InputStream</code>
1445          * @throws IllegalArgumentException if type of <code>name</code> is
1446          *         not serializable or if the field type is incorrect
1447          */

1448         public abstract int get(String name, int val) throws IOException;
1449
1450         /**
1451          * Get the value of the named long field from the persistent field.
1452          *
1453          * @param  name the name of the field
1454          * @param  val the default value to use if <code>name</code> does not
1455          *         have a value
1456          * @return the value of the named <code>long</code> field
1457          * @throws IOException if there are I/O errors while reading from the
1458          *         underlying <code>InputStream</code>
1459          * @throws IllegalArgumentException if type of <code>name</code> is
1460          *         not serializable or if the field type is incorrect
1461          */

1462         public abstract long get(String name, long val) throws IOException;
1463
1464         /**
1465          * Get the value of the named float field from the persistent field.
1466          *
1467          * @param  name the name of the field
1468          * @param  val the default value to use if <code>name</code> does not
1469          *         have a value
1470          * @return the value of the named <code>float</code> field
1471          * @throws IOException if there are I/O errors while reading from the
1472          *         underlying <code>InputStream</code>
1473          * @throws IllegalArgumentException if type of <code>name</code> is
1474          *         not serializable or if the field type is incorrect
1475          */

1476         public abstract float get(String name, float val) throws IOException;
1477
1478         /**
1479          * Get the value of the named double field from the persistent field.
1480          *
1481          * @param  name the name of the field
1482          * @param  val the default value to use if <code>name</code> does not
1483          *         have a value
1484          * @return the value of the named <code>double</code> field
1485          * @throws IOException if there are I/O errors while reading from the
1486          *         underlying <code>InputStream</code>
1487          * @throws IllegalArgumentException if type of <code>name</code> is
1488          *         not serializable or if the field type is incorrect
1489          */

1490         public abstract double get(String name, double val) throws IOException;
1491
1492         /**
1493          * Get the value of the named Object field from the persistent field.
1494          *
1495          * @param  name the name of the field
1496          * @param  val the default value to use if <code>name</code> does not
1497          *         have a value
1498          * @return the value of the named <code>Object</code> field
1499          * @throws IOException if there are I/O errors while reading from the
1500          *         underlying <code>InputStream</code>
1501          * @throws IllegalArgumentException if type of <code>name</code> is
1502          *         not serializable or if the field type is incorrect
1503          */

1504         public abstract Object get(String name, Object val) throws IOException;
1505     }
1506
1507     /**
1508      * Verifies that this (possibly subclass) instance can be constructed
1509      * without violating security constraints: the subclass must not override
1510      * security-sensitive non-final methods, or else the
1511      * "enableSubclassImplementation" SerializablePermission is checked.
1512      */

1513     private void verifySubclass() {
1514         Class<?> cl = getClass();
1515         if (cl == ObjectInputStream.class) {
1516             return;
1517         }
1518         SecurityManager sm = System.getSecurityManager();
1519         if (sm == null) {
1520             return;
1521         }
1522         processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
1523         WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
1524         Boolean result = Caches.subclassAudits.get(key);
1525         if (result == null) {
1526             result = auditSubclass(cl);
1527             Caches.subclassAudits.putIfAbsent(key, result);
1528         }
1529         if (!result) {
1530             sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
1531         }
1532     }
1533
1534     /**
1535      * Performs reflective checks on given subclass to verify that it doesn't
1536      * override security-sensitive non-final methods.  Returns TRUE if subclass
1537      * is "safe", FALSE otherwise.
1538      */

1539     private static Boolean auditSubclass(Class<?> subcl) {
1540         return AccessController.doPrivileged(
1541             new PrivilegedAction<Boolean>() {
1542                 public Boolean run() {
1543                     for (Class<?> cl = subcl;
1544                          cl != ObjectInputStream.class;
1545                          cl = cl.getSuperclass())
1546                     {
1547                         try {
1548                             cl.getDeclaredMethod(
1549                                 "readUnshared", (Class[]) null);
1550                             return Boolean.FALSE;
1551                         } catch (NoSuchMethodException ex) {
1552                         }
1553                         try {
1554                             cl.getDeclaredMethod("readFields", (Class[]) null);
1555                             return Boolean.FALSE;
1556                         } catch (NoSuchMethodException ex) {
1557                         }
1558                     }
1559                     return Boolean.TRUE;
1560                 }
1561             }
1562         );
1563     }
1564
1565     /**
1566      * Clears internal data structures.
1567      */

1568     private void clear() {
1569         handles.clear();
1570         vlist.clear();
1571     }
1572
1573     /**
1574      * Underlying readObject implementation.
1575      * @param type a type expected to be deserialized; non-null
1576      * @param unshared true if the object can not be a reference to a shared object, otherwise false
1577      */

1578     private Object readObject0(Class<?> type, boolean unshared) throws IOException {
1579         boolean oldMode = bin.getBlockDataMode();
1580         if (oldMode) {
1581             int remain = bin.currentBlockRemaining();
1582             if (remain > 0) {
1583                 throw new OptionalDataException(remain);
1584             } else if (defaultDataEnd) {
1585                 /*
1586                  * Fix for 4360508: stream is currently at the end of a field
1587                  * value block written via default serialization; since there
1588                  * is no terminating TC_ENDBLOCKDATA tag, simulate
1589                  * end-of-custom-data behavior explicitly.
1590                  */

1591                 throw new OptionalDataException(true);
1592             }
1593             bin.setBlockDataMode(false);
1594         }
1595
1596         byte tc;
1597         while ((tc = bin.peekByte()) == TC_RESET) {
1598             bin.readByte();
1599             handleReset();
1600         }
1601
1602         depth++;
1603         totalObjectRefs++;
1604         try {
1605             switch (tc) {
1606                 case TC_NULL:
1607                     return readNull();
1608
1609                 case TC_REFERENCE:
1610                     // check the type of the existing object
1611                     return type.cast(readHandle(unshared));
1612
1613                 case TC_CLASS:
1614                     if (type == String.class) {
1615                         throw new ClassCastException("Cannot cast a class to java.lang.String");
1616                     }
1617                     return readClass(unshared);
1618
1619                 case TC_CLASSDESC:
1620                 case TC_PROXYCLASSDESC:
1621                     if (type == String.class) {
1622                         throw new ClassCastException("Cannot cast a class to java.lang.String");
1623                     }
1624                     return readClassDesc(unshared);
1625
1626                 case TC_STRING:
1627                 case TC_LONGSTRING:
1628                     return checkResolve(readString(unshared));
1629
1630                 case TC_ARRAY:
1631                     if (type == String.class) {
1632                         throw new ClassCastException("Cannot cast an array to java.lang.String");
1633                     }
1634                     return checkResolve(readArray(unshared));
1635
1636                 case TC_ENUM:
1637                     if (type == String.class) {
1638                         throw new ClassCastException("Cannot cast an enum to java.lang.String");
1639                     }
1640                     return checkResolve(readEnum(unshared));
1641
1642                 case TC_OBJECT:
1643                     if (type == String.class) {
1644                         throw new ClassCastException("Cannot cast an object to java.lang.String");
1645                     }
1646                     return checkResolve(readOrdinaryObject(unshared));
1647
1648                 case TC_EXCEPTION:
1649                     if (type == String.class) {
1650                         throw new ClassCastException("Cannot cast an exception to java.lang.String");
1651                     }
1652                     IOException ex = readFatalException();
1653                     throw new WriteAbortedException("writing aborted", ex);
1654
1655                 case TC_BLOCKDATA:
1656                 case TC_BLOCKDATALONG:
1657                     if (oldMode) {
1658                         bin.setBlockDataMode(true);
1659                         bin.peek();             // force header read
1660                         throw new OptionalDataException(
1661                             bin.currentBlockRemaining());
1662                     } else {
1663                         throw new StreamCorruptedException(
1664                             "unexpected block data");
1665                     }
1666
1667                 case TC_ENDBLOCKDATA:
1668                     if (oldMode) {
1669                         throw new OptionalDataException(true);
1670                     } else {
1671                         throw new StreamCorruptedException(
1672                             "unexpected end of block data");
1673                     }
1674
1675                 default:
1676                     throw new StreamCorruptedException(
1677                         String.format("invalid type code: %02X", tc));
1678             }
1679         } finally {
1680             depth--;
1681             bin.setBlockDataMode(oldMode);
1682         }
1683     }
1684
1685     /**
1686      * If resolveObject has been enabled and given object does not have an
1687      * exception associated with it, calls resolveObject to determine
1688      * replacement for object, and updates handle table accordingly.  Returns
1689      * replacement object, or echoes provided object if no replacement
1690      * occurred.  Expects that passHandle is set to given object's handle prior
1691      * to calling this method.
1692      */

1693     private Object checkResolve(Object obj) throws IOException {
1694         if (!enableResolve || handles.lookupException(passHandle) != null) {
1695             return obj;
1696         }
1697         Object rep = resolveObject(obj);
1698         if (rep != obj) {
1699             // The type of the original object has been filtered but resolveObject
1700             // may have replaced it;  filter the replacement's type
1701             if (rep != null) {
1702                 if (rep.getClass().isArray()) {
1703                     filterCheck(rep.getClass(), Array.getLength(rep));
1704                 } else {
1705                     filterCheck(rep.getClass(), -1);
1706                 }
1707             }
1708             handles.setObject(passHandle, rep);
1709         }
1710         return rep;
1711     }
1712
1713     /**
1714      * Reads string without allowing it to be replaced in stream.  Called from
1715      * within ObjectStreamClass.read().
1716      */

1717     String readTypeString() throws IOException {
1718         int oldHandle = passHandle;
1719         try {
1720             byte tc = bin.peekByte();
1721             switch (tc) {
1722                 case TC_NULL:
1723                     return (String) readNull();
1724
1725                 case TC_REFERENCE:
1726                     return (String) readHandle(false);
1727
1728                 case TC_STRING:
1729                 case TC_LONGSTRING:
1730                     return readString(false);
1731
1732                 default:
1733                     throw new StreamCorruptedException(
1734                         String.format("invalid type code: %02X", tc));
1735             }
1736         } finally {
1737             passHandle = oldHandle;
1738         }
1739     }
1740
1741     /**
1742      * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
1743      */

1744     private Object readNull() throws IOException {
1745         if (bin.readByte() != TC_NULL) {
1746             throw new InternalError();
1747         }
1748         passHandle = NULL_HANDLE;
1749         return null;
1750     }
1751
1752     /**
1753      * Reads in object handle, sets passHandle to the read handle, and returns
1754      * object associated with the handle.
1755      */

1756     private Object readHandle(boolean unshared) throws IOException {
1757         if (bin.readByte() != TC_REFERENCE) {
1758             throw new InternalError();
1759         }
1760         passHandle = bin.readInt() - baseWireHandle;
1761         if (passHandle < 0 || passHandle >= handles.size()) {
1762             throw new StreamCorruptedException(
1763                 String.format("invalid handle value: %08X", passHandle +
1764                 baseWireHandle));
1765         }
1766         if (unshared) {
1767             // REMIND: what type of exception to throw here?
1768             throw new InvalidObjectException(
1769                 "cannot read back reference as unshared");
1770         }
1771
1772         Object obj = handles.lookupObject(passHandle);
1773         if (obj == unsharedMarker) {
1774             // REMIND: what type of exception to throw here?
1775             throw new InvalidObjectException(
1776                 "cannot read back reference to unshared object");
1777         }
1778         filterCheck(null, -1);       // just a check for number of references, depth, no class
1779         return obj;
1780     }
1781
1782     /**
1783      * Reads in and returns class object.  Sets passHandle to class object's
1784      * assigned handle.  Returns null if class is unresolvable (in which case a
1785      * ClassNotFoundException will be associated with the class' handle in the
1786      * handle table).
1787      */

1788     private Class<?> readClass(boolean unshared) throws IOException {
1789         if (bin.readByte() != TC_CLASS) {
1790             throw new InternalError();
1791         }
1792         ObjectStreamClass desc = readClassDesc(false);
1793         Class<?> cl = desc.forClass();
1794         passHandle = handles.assign(unshared ? unsharedMarker : cl);
1795
1796         ClassNotFoundException resolveEx = desc.getResolveException();
1797         if (resolveEx != null) {
1798             handles.markException(passHandle, resolveEx);
1799         }
1800
1801         handles.finish(passHandle);
1802         return cl;
1803     }
1804
1805     /**
1806      * Reads in and returns (possibly nullclass descriptor.  Sets passHandle
1807      * to class descriptor's assigned handle.  If class descriptor cannot be
1808      * resolved to a class in the local VM, a ClassNotFoundException is
1809      * associated with the class descriptor's handle.
1810      */

1811     private ObjectStreamClass readClassDesc(boolean unshared)
1812         throws IOException
1813     {
1814         byte tc = bin.peekByte();
1815         ObjectStreamClass descriptor;
1816         switch (tc) {
1817             case TC_NULL:
1818                 descriptor = (ObjectStreamClass) readNull();
1819                 break;
1820             case TC_REFERENCE:
1821                 descriptor = (ObjectStreamClass) readHandle(unshared);
1822                 break;
1823             case TC_PROXYCLASSDESC:
1824                 descriptor = readProxyDesc(unshared);
1825                 break;
1826             case TC_CLASSDESC:
1827                 descriptor = readNonProxyDesc(unshared);
1828                 break;
1829             default:
1830                 throw new StreamCorruptedException(
1831                     String.format("invalid type code: %02X", tc));
1832         }
1833         return descriptor;
1834     }
1835
1836     private boolean isCustomSubclass() {
1837         // Return true if this class is a custom subclass of ObjectInputStream
1838         return getClass().getClassLoader()
1839                     != ObjectInputStream.class.getClassLoader();
1840     }
1841
1842     /**
1843      * Reads in and returns class descriptor for a dynamic proxy class.  Sets
1844      * passHandle to proxy class descriptor's assigned handle.  If proxy class
1845      * descriptor cannot be resolved to a class in the local VM, a
1846      * ClassNotFoundException is associated with the descriptor's handle.
1847      */

1848     private ObjectStreamClass readProxyDesc(boolean unshared)
1849         throws IOException
1850     {
1851         if (bin.readByte() != TC_PROXYCLASSDESC) {
1852             throw new InternalError();
1853         }
1854
1855         ObjectStreamClass desc = new ObjectStreamClass();
1856         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1857         passHandle = NULL_HANDLE;
1858
1859         int numIfaces = bin.readInt();
1860         if (numIfaces > 65535) {
1861             throw new InvalidObjectException("interface limit exceeded: "
1862                     + numIfaces);
1863         }
1864         String[] ifaces = new String[numIfaces];
1865         for (int i = 0; i < numIfaces; i++) {
1866             ifaces[i] = bin.readUTF();
1867         }
1868
1869         Class<?> cl = null;
1870         ClassNotFoundException resolveEx = null;
1871         bin.setBlockDataMode(true);
1872         try {
1873             if ((cl = resolveProxyClass(ifaces)) == null) {
1874                 resolveEx = new ClassNotFoundException("null class");
1875             } else if (!Proxy.isProxyClass(cl)) {
1876                 throw new InvalidClassException("Not a proxy");
1877             } else {
1878                 // ReflectUtil.checkProxyPackageAccess makes a test
1879                 // equivalent to isCustomSubclass so there's no need
1880                 // to condition this call to isCustomSubclass == true here.
1881                 ReflectUtil.checkProxyPackageAccess(
1882                         getClass().getClassLoader(),
1883                         cl.getInterfaces());
1884                 // Filter the interfaces
1885                 for (Class<?> clazz : cl.getInterfaces()) {
1886                     filterCheck(clazz, -1);
1887                 }
1888             }
1889         } catch (ClassNotFoundException ex) {
1890             resolveEx = ex;
1891         }
1892
1893         // Call filterCheck on the class before reading anything else
1894         filterCheck(cl, -1);
1895
1896         skipCustomData();
1897
1898         try {
1899             totalObjectRefs++;
1900             depth++;
1901             desc.initProxy(cl, resolveEx, readClassDesc(false));
1902         } finally {
1903             depth--;
1904         }
1905
1906         handles.finish(descHandle);
1907         passHandle = descHandle;
1908         return desc;
1909     }
1910
1911     /**
1912      * Reads in and returns class descriptor for a class that is not a dynamic
1913      * proxy class.  Sets passHandle to class descriptor's assigned handle.  If
1914      * class descriptor cannot be resolved to a class in the local VM, a
1915      * ClassNotFoundException is associated with the descriptor's handle.
1916      */

1917     private ObjectStreamClass readNonProxyDesc(boolean unshared)
1918         throws IOException
1919     {
1920         if (bin.readByte() != TC_CLASSDESC) {
1921             throw new InternalError();
1922         }
1923
1924         ObjectStreamClass desc = new ObjectStreamClass();
1925         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1926         passHandle = NULL_HANDLE;
1927
1928         ObjectStreamClass readDesc;
1929         try {
1930             readDesc = readClassDescriptor();
1931         } catch (ClassNotFoundException ex) {
1932             throw (IOException) new InvalidClassException(
1933                 "failed to read class descriptor").initCause(ex);
1934         }
1935
1936         Class<?> cl = null;
1937         ClassNotFoundException resolveEx = null;
1938         bin.setBlockDataMode(true);
1939         final boolean checksRequired = isCustomSubclass();
1940         try {
1941             if ((cl = resolveClass(readDesc)) == null) {
1942                 resolveEx = new ClassNotFoundException("null class");
1943             } else if (checksRequired) {
1944                 ReflectUtil.checkPackageAccess(cl);
1945             }
1946         } catch (ClassNotFoundException ex) {
1947             resolveEx = ex;
1948         }
1949
1950         // Call filterCheck on the class before reading anything else
1951         filterCheck(cl, -1);
1952
1953         skipCustomData();
1954
1955         try {
1956             totalObjectRefs++;
1957             depth++;
1958             desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
1959         } finally {
1960             depth--;
1961         }
1962
1963         handles.finish(descHandle);
1964         passHandle = descHandle;
1965
1966         return desc;
1967     }
1968
1969     /**
1970      * Reads in and returns new string.  Sets passHandle to new string's
1971      * assigned handle.
1972      */

1973     private String readString(boolean unshared) throws IOException {
1974         String str;
1975         byte tc = bin.readByte();
1976         switch (tc) {
1977             case TC_STRING:
1978                 str = bin.readUTF();
1979                 break;
1980
1981             case TC_LONGSTRING:
1982                 str = bin.readLongUTF();
1983                 break;
1984
1985             default:
1986                 throw new StreamCorruptedException(
1987                     String.format("invalid type code: %02X", tc));
1988         }
1989         passHandle = handles.assign(unshared ? unsharedMarker : str);
1990         handles.finish(passHandle);
1991         return str;
1992     }
1993
1994     /**
1995      * Reads in and returns array object, or null if array class is
1996      * unresolvable.  Sets passHandle to array's assigned handle.
1997      */

1998     private Object readArray(boolean unshared) throws IOException {
1999         if (bin.readByte() != TC_ARRAY) {
2000             throw new InternalError();
2001         }
2002
2003         ObjectStreamClass desc = readClassDesc(false);
2004         int len = bin.readInt();
2005
2006         filterCheck(desc.forClass(), len);
2007
2008         Object array = null;
2009         Class<?> cl, ccl = null;
2010         if ((cl = desc.forClass()) != null) {
2011             ccl = cl.getComponentType();
2012             array = Array.newInstance(ccl, len);
2013         }
2014
2015         int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
2016         ClassNotFoundException resolveEx = desc.getResolveException();
2017         if (resolveEx != null) {
2018             handles.markException(arrayHandle, resolveEx);
2019         }
2020
2021         if (ccl == null) {
2022             for (int i = 0; i < len; i++) {
2023                 readObject0(Object.classfalse);
2024             }
2025         } else if (ccl.isPrimitive()) {
2026             if (ccl == Integer.TYPE) {
2027                 bin.readInts((int[]) array, 0, len);
2028             } else if (ccl == Byte.TYPE) {
2029                 bin.readFully((byte[]) array, 0, len, true);
2030             } else if (ccl == Long.TYPE) {
2031                 bin.readLongs((long[]) array, 0, len);
2032             } else if (ccl == Float.TYPE) {
2033                 bin.readFloats((float[]) array, 0, len);
2034             } else if (ccl == Double.TYPE) {
2035                 bin.readDoubles((double[]) array, 0, len);
2036             } else if (ccl == Short.TYPE) {
2037                 bin.readShorts((short[]) array, 0, len);
2038             } else if (ccl == Character.TYPE) {
2039                 bin.readChars((char[]) array, 0, len);
2040             } else if (ccl == Boolean.TYPE) {
2041                 bin.readBooleans((boolean[]) array, 0, len);
2042             } else {
2043                 throw new InternalError();
2044             }
2045         } else {
2046             Object[] oa = (Object[]) array;
2047             for (int i = 0; i < len; i++) {
2048                 oa[i] = readObject0(Object.classfalse);
2049                 handles.markDependency(arrayHandle, passHandle);
2050             }
2051         }
2052
2053         handles.finish(arrayHandle);
2054         passHandle = arrayHandle;
2055         return array;
2056     }
2057
2058     /**
2059      * Reads in and returns enum constant, or null if enum type is
2060      * unresolvable.  Sets passHandle to enum constant's assigned handle.
2061      */

2062     private Enum<?> readEnum(boolean unshared) throws IOException {
2063         if (bin.readByte() != TC_ENUM) {
2064             throw new InternalError();
2065         }
2066
2067         ObjectStreamClass desc = readClassDesc(false);
2068         if (!desc.isEnum()) {
2069             throw new InvalidClassException("non-enum class: " + desc);
2070         }
2071
2072         int enumHandle = handles.assign(unshared ? unsharedMarker : null);
2073         ClassNotFoundException resolveEx = desc.getResolveException();
2074         if (resolveEx != null) {
2075             handles.markException(enumHandle, resolveEx);
2076         }
2077
2078         String name = readString(false);
2079         Enum<?> result = null;
2080         Class<?> cl = desc.forClass();
2081         if (cl != null) {
2082             try {
2083                 @SuppressWarnings("unchecked")
2084                 Enum<?> en = Enum.valueOf((Class)cl, name);
2085                 result = en;
2086             } catch (IllegalArgumentException ex) {
2087                 throw (IOException) new InvalidObjectException(
2088                     "enum constant " + name + " does not exist in " +
2089                     cl).initCause(ex);
2090             }
2091             if (!unshared) {
2092                 handles.setObject(enumHandle, result);
2093             }
2094         }
2095
2096         handles.finish(enumHandle);
2097         passHandle = enumHandle;
2098         return result;
2099     }
2100
2101     /**
2102      * Reads and returns "ordinary" (i.e., not a String, Class,
2103      * ObjectStreamClass, array, or enum constant) object, or null if object's
2104      * class is unresolvable (in which case a ClassNotFoundException will be
2105      * associated with object's handle).  Sets passHandle to object's assigned
2106      * handle.
2107      */

2108     private Object readOrdinaryObject(boolean unshared)
2109         throws IOException
2110     {
2111         if (bin.readByte() != TC_OBJECT) {
2112             throw new InternalError();
2113         }
2114
2115         ObjectStreamClass desc = readClassDesc(false);
2116         desc.checkDeserialize();
2117
2118         Class<?> cl = desc.forClass();
2119         if (cl == String.class || cl == Class.class
2120                 || cl == ObjectStreamClass.class) {
2121             throw new InvalidClassException("invalid class descriptor");
2122         }
2123
2124         Object obj;
2125         try {
2126             obj = desc.isInstantiable() ? desc.newInstance() : null;
2127         } catch (Exception ex) {
2128             throw (IOException) new InvalidClassException(
2129                 desc.forClass().getName(),
2130                 "unable to create instance").initCause(ex);
2131         }
2132
2133         passHandle = handles.assign(unshared ? unsharedMarker : obj);
2134         ClassNotFoundException resolveEx = desc.getResolveException();
2135         if (resolveEx != null) {
2136             handles.markException(passHandle, resolveEx);
2137         }
2138
2139         if (desc.isExternalizable()) {
2140             readExternalData((Externalizable) obj, desc);
2141         } else {
2142             readSerialData(obj, desc);
2143         }
2144
2145         handles.finish(passHandle);
2146
2147         if (obj != null &&
2148             handles.lookupException(passHandle) == null &&
2149             desc.hasReadResolveMethod())
2150         {
2151             Object rep = desc.invokeReadResolve(obj);
2152             if (unshared && rep.getClass().isArray()) {
2153                 rep = cloneArray(rep);
2154             }
2155             if (rep != obj) {
2156                 // Filter the replacement object
2157                 if (rep != null) {
2158                     if (rep.getClass().isArray()) {
2159                         filterCheck(rep.getClass(), Array.getLength(rep));
2160                     } else {
2161                         filterCheck(rep.getClass(), -1);
2162                     }
2163                 }
2164                 handles.setObject(passHandle, obj = rep);
2165             }
2166         }
2167
2168         return obj;
2169     }
2170
2171     /**
2172      * If obj is non-null, reads externalizable data by invoking readExternal()
2173      * method of obj; otherwise, attempts to skip over externalizable data.
2174      * Expects that passHandle is set to obj's handle before this method is
2175      * called.
2176      */

2177     private void readExternalData(Externalizable obj, ObjectStreamClass desc)
2178         throws IOException
2179     {
2180         SerialCallbackContext oldContext = curContext;
2181         if (oldContext != null)
2182             oldContext.check();
2183         curContext = null;
2184         try {
2185             boolean blocked = desc.hasBlockExternalData();
2186             if (blocked) {
2187                 bin.setBlockDataMode(true);
2188             }
2189             if (obj != null) {
2190                 try {
2191                     obj.readExternal(this);
2192                 } catch (ClassNotFoundException ex) {
2193                     /*
2194                      * In most cases, the handle table has already propagated
2195                      * a CNFException to passHandle at this point; this mark
2196                      * call is included to address cases where the readExternal
2197                      * method has cons'ed and thrown a new CNFException of its
2198                      * own.
2199                      */

2200                      handles.markException(passHandle, ex);
2201                 }
2202             }
2203             if (blocked) {
2204                 skipCustomData();
2205             }
2206         } finally {
2207             if (oldContext != null)
2208                 oldContext.check();
2209             curContext = oldContext;
2210         }
2211         /*
2212          * At this point, if the externalizable data was not written in
2213          * block-data form and either the externalizable class doesn't exist
2214          * locally (i.e., obj == null) or readExternal() just threw a
2215          * CNFException, then the stream is probably in an inconsistent state,
2216          * since some (or all) of the externalizable data may not have been
2217          * consumed.  Since there's no "correct" action to take in this case,
2218          * we mimic the behavior of past serialization implementations and
2219          * blindly hope that the stream is in sync; if it isn't and additional
2220          * externalizable data remains in the stream, a subsequent read will
2221          * most likely throw a StreamCorruptedException.
2222          */

2223     }
2224
2225     /**
2226      * Reads (or attempts to skip, if obj is null or is tagged with a
2227      * ClassNotFoundException) instance data for each serializable class of
2228      * object in stream, from superclass to subclass.  Expects that passHandle
2229      * is set to obj's handle before this method is called.
2230      */

2231     private void readSerialData(Object obj, ObjectStreamClass desc)
2232         throws IOException
2233     {
2234         ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
2235         // Best effort Failure Atomicity; slotValues will be non-null if field
2236         // values can be set after reading all field data in the hierarchy.
2237         // Field values can only be set after reading all data if there are no
2238         // user observable methods in the hierarchy, readObject(NoData). The
2239         // top most Serializable class in the hierarchy can be skipped.
2240         FieldValues[] slotValues = null;
2241
2242         boolean hasSpecialReadMethod = false;
2243         for (int i = 1; i < slots.length; i++) {
2244             ObjectStreamClass slotDesc = slots[i].desc;
2245             if (slotDesc.hasReadObjectMethod()
2246                   || slotDesc.hasReadObjectNoDataMethod()) {
2247                 hasSpecialReadMethod = true;
2248                 break;
2249             }
2250         }
2251         // No special read methods, can store values and defer setting.
2252         if (!hasSpecialReadMethod)
2253             slotValues = new FieldValues[slots.length];
2254
2255         for (int i = 0; i < slots.length; i++) {
2256             ObjectStreamClass slotDesc = slots[i].desc;
2257
2258             if (slots[i].hasData) {
2259                 if (obj == null || handles.lookupException(passHandle) != null) {
2260                     defaultReadFields(null, slotDesc); // skip field values
2261                 } else if (slotDesc.hasReadObjectMethod()) {
2262                     ThreadDeath t = null;
2263                     boolean reset = false;
2264                     SerialCallbackContext oldContext = curContext;
2265                     if (oldContext != null)
2266                         oldContext.check();
2267                     try {
2268                         curContext = new SerialCallbackContext(obj, slotDesc);
2269
2270                         bin.setBlockDataMode(true);
2271                         slotDesc.invokeReadObject(obj, this);
2272                     } catch (ClassNotFoundException ex) {
2273                         /*
2274                          * In most cases, the handle table has already
2275                          * propagated a CNFException to passHandle at this
2276                          * point; this mark call is included to address cases
2277                          * where the custom readObject method has cons'ed and
2278                          * thrown a new CNFException of its own.
2279                          */

2280                         handles.markException(passHandle, ex);
2281                     } finally {
2282                         do {
2283                             try {
2284                                 curContext.setUsed();
2285                                 if (oldContext!= null)
2286                                     oldContext.check();
2287                                 curContext = oldContext;
2288                                 reset = true;
2289                             } catch (ThreadDeath x) {
2290                                 t = x;  // defer until reset is true
2291                             }
2292                         } while (!reset);
2293                         if (t != null)
2294                             throw t;
2295                     }
2296
2297                     /*
2298                      * defaultDataEnd may have been set indirectly by custom
2299                      * readObject() method when calling defaultReadObject() or
2300                      * readFields(); clear it to restore normal read behavior.
2301                      */

2302                     defaultDataEnd = false;
2303                 } else {
2304                     FieldValues vals = defaultReadFields(obj, slotDesc);
2305                     if (slotValues != null) {
2306                         slotValues[i] = vals;
2307                     } else if (obj != null) {
2308                         defaultCheckFieldValues(obj, slotDesc, vals);
2309                         defaultSetFieldValues(obj, slotDesc, vals);
2310                     }
2311                 }
2312
2313                 if (slotDesc.hasWriteObjectData()) {
2314                     skipCustomData();
2315                 } else {
2316                     bin.setBlockDataMode(false);
2317                 }
2318             } else {
2319                 if (obj != null &&
2320                     slotDesc.hasReadObjectNoDataMethod() &&
2321                     handles.lookupException(passHandle) == null)
2322                 {
2323                     slotDesc.invokeReadObjectNoData(obj);
2324                 }
2325             }
2326         }
2327
2328         if (obj != null && slotValues != null) {
2329             // Check that the non-primitive types are assignable for all slots
2330             // before assigning.
2331             for (int i = 0; i < slots.length; i++) {
2332                 if (slotValues[i] != null)
2333                     defaultCheckFieldValues(obj, slots[i].desc, slotValues[i]);
2334             }
2335             for (int i = 0; i < slots.length; i++) {
2336                 if (slotValues[i] != null)
2337                     defaultSetFieldValues(obj, slots[i].desc, slotValues[i]);
2338             }
2339         }
2340     }
2341
2342     /**
2343      * Skips over all block data and objects until TC_ENDBLOCKDATA is
2344      * encountered.
2345      */

2346     private void skipCustomData() throws IOException {
2347         int oldHandle = passHandle;
2348         for (;;) {
2349             if (bin.getBlockDataMode()) {
2350                 bin.skipBlockData();
2351                 bin.setBlockDataMode(false);
2352             }
2353             switch (bin.peekByte()) {
2354                 case TC_BLOCKDATA:
2355                 case TC_BLOCKDATALONG:
2356                     bin.setBlockDataMode(true);
2357                     break;
2358
2359                 case TC_ENDBLOCKDATA:
2360                     bin.readByte();
2361                     passHandle = oldHandle;
2362                     return;
2363
2364                 default:
2365                     readObject0(Object.classfalse);
2366                     break;
2367             }
2368         }
2369     }
2370
2371     private class FieldValues {
2372         final byte[] primValues;
2373         final Object[] objValues;
2374
2375         FieldValues(byte[] primValues, Object[] objValues) {
2376             this.primValues = primValues;
2377             this.objValues = objValues;
2378         }
2379     }
2380
2381     /**
2382      * Reads in values of serializable fields declared by given class
2383      * descriptor. Expects that passHandle is set to obj's handle before this
2384      * method is called.
2385      */

2386     private FieldValues defaultReadFields(Object obj, ObjectStreamClass desc)
2387         throws IOException
2388     {
2389         Class<?> cl = desc.forClass();
2390         if (cl != null && obj != null && !cl.isInstance(obj)) {
2391             throw new ClassCastException();
2392         }
2393
2394         byte[] primVals = null;
2395         int primDataSize = desc.getPrimDataSize();
2396         if (primDataSize > 0) {
2397             primVals = new byte[primDataSize];
2398             bin.readFully(primVals, 0, primDataSize, false);
2399         }
2400
2401         Object[] objVals = null;
2402         int numObjFields = desc.getNumObjFields();
2403         if (numObjFields > 0) {
2404             int objHandle = passHandle;
2405             ObjectStreamField[] fields = desc.getFields(false);
2406             objVals = new Object[numObjFields];
2407             int numPrimFields = fields.length - objVals.length;
2408             for (int i = 0; i < objVals.length; i++) {
2409                 ObjectStreamField f = fields[numPrimFields + i];
2410                 objVals[i] = readObject0(Object.class, f.isUnshared());
2411                 if (f.getField() != null) {
2412                     handles.markDependency(objHandle, passHandle);
2413                 }
2414             }
2415             passHandle = objHandle;
2416         }
2417
2418         return new FieldValues(primVals, objVals);
2419     }
2420
2421     /** Throws ClassCastException if any value is not assignable. */
2422     private void defaultCheckFieldValues(Object obj, ObjectStreamClass desc,
2423                                          FieldValues values) {
2424         Object[] objectValues = values.objValues;
2425         if (objectValues != null)
2426             desc.checkObjFieldValueTypes(obj, objectValues);
2427     }
2428
2429     /** Sets field values in obj. */
2430     private void defaultSetFieldValues(Object obj, ObjectStreamClass desc,
2431                                        FieldValues values) {
2432         byte[] primValues = values.primValues;
2433         Object[] objectValues = values.objValues;
2434
2435         if (primValues != null)
2436             desc.setPrimFieldValues(obj, primValues);
2437         if (objectValues != null)
2438             desc.setObjFieldValues(obj, objectValues);
2439     }
2440
2441     /**
2442      * Reads in and returns IOException that caused serialization to abort.
2443      * All stream state is discarded prior to reading in fatal exception.  Sets
2444      * passHandle to fatal exception's handle.
2445      */

2446     private IOException readFatalException() throws IOException {
2447         if (bin.readByte() != TC_EXCEPTION) {
2448             throw new InternalError();
2449         }
2450         clear();
2451         return (IOException) readObject0(Object.classfalse);
2452     }
2453
2454     /**
2455      * If recursion depth is 0, clears internal data structures; otherwise,
2456      * throws a StreamCorruptedException.  This method is called when a
2457      * TC_RESET typecode is encountered.
2458      */

2459     private void handleReset() throws StreamCorruptedException {
2460         if (depth > 0) {
2461             throw new StreamCorruptedException(
2462                 "unexpected reset; recursion depth: " + depth);
2463         }
2464         clear();
2465     }
2466
2467     /**
2468      * Converts specified span of bytes into float values.
2469      */

2470     // REMIND: remove once hotspot inlines Float.intBitsToFloat
2471     private static native void bytesToFloats(byte[] src, int srcpos,
2472                                              float[] dst, int dstpos,
2473                                              int nfloats);
2474
2475     /**
2476      * Converts specified span of bytes into double values.
2477      */

2478     // REMIND: remove once hotspot inlines Double.longBitsToDouble
2479     private static native void bytesToDoubles(byte[] src, int srcpos,
2480                                               double[] dst, int dstpos,
2481                                               int ndoubles);
2482
2483     /**
2484      * Returns the first non-null and non-platform class loader (not counting
2485      * class loaders of generated reflection implementation classes) up the
2486      * execution stack, or the platform class loader if only code from the
2487      * bootstrap and platform class loader is on the stack.
2488      */

2489     private static ClassLoader latestUserDefinedLoader() {
2490         return jdk.internal.misc.VM.latestUserDefinedLoader();
2491     }
2492
2493     /**
2494      * Default GetField implementation.
2495      */

2496     private class GetFieldImpl extends GetField {
2497
2498         /** class descriptor describing serializable fields */
2499         private final ObjectStreamClass desc;
2500         /** primitive field values */
2501         private final byte[] primVals;
2502         /** object field values */
2503         private final Object[] objVals;
2504         /** object field value handles */
2505         private final int[] objHandles;
2506
2507         /**
2508          * Creates GetFieldImpl object for reading fields defined in given
2509          * class descriptor.
2510          */

2511         GetFieldImpl(ObjectStreamClass desc) {
2512             this.desc = desc;
2513             primVals = new byte[desc.getPrimDataSize()];
2514             objVals = new Object[desc.getNumObjFields()];
2515             objHandles = new int[objVals.length];
2516         }
2517
2518         public ObjectStreamClass getObjectStreamClass() {
2519             return desc;
2520         }
2521
2522         public boolean defaulted(String name) throws IOException {
2523             return (getFieldOffset(name, null) < 0);
2524         }
2525
2526         public boolean get(String name, boolean val) throws IOException {
2527             int off = getFieldOffset(name, Boolean.TYPE);
2528             return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
2529         }
2530
2531         public byte get(String name, byte val) throws IOException {
2532             int off = getFieldOffset(name, Byte.TYPE);
2533             return (off >= 0) ? primVals[off] : val;
2534         }
2535
2536         public char get(String name, char val) throws IOException {
2537             int off = getFieldOffset(name, Character.TYPE);
2538             return (off >= 0) ? Bits.getChar(primVals, off) : val;
2539         }
2540
2541         public short get(String name, short val) throws IOException {
2542             int off = getFieldOffset(name, Short.TYPE);
2543             return (off >= 0) ? Bits.getShort(primVals, off) : val;
2544         }
2545
2546         public int get(String name, int val) throws IOException {
2547             int off = getFieldOffset(name, Integer.TYPE);
2548             return (off >= 0) ? Bits.getInt(primVals, off) : val;
2549         }
2550
2551         public float get(String name, float val) throws IOException {
2552             int off = getFieldOffset(name, Float.TYPE);
2553             return (off >= 0) ? Bits.getFloat(primVals, off) : val;
2554         }
2555
2556         public long get(String name, long val) throws IOException {
2557             int off = getFieldOffset(name, Long.TYPE);
2558             return (off >= 0) ? Bits.getLong(primVals, off) : val;
2559         }
2560
2561         public double get(String name, double val) throws IOException {
2562             int off = getFieldOffset(name, Double.TYPE);
2563             return (off >= 0) ? Bits.getDouble(primVals, off) : val;
2564         }
2565
2566         public Object get(String name, Object val) throws IOException {
2567             int off = getFieldOffset(name, Object.class);
2568             if (off >= 0) {
2569                 int objHandle = objHandles[off];
2570                 handles.markDependency(passHandle, objHandle);
2571                 return (handles.lookupException(objHandle) == null) ?
2572                     objVals[off] : null;
2573             } else {
2574                 return val;
2575             }
2576         }
2577
2578         /**
2579          * Reads primitive and object field values from stream.
2580          */

2581         void readFields() throws IOException {
2582             bin.readFully(primVals, 0, primVals.length, false);
2583
2584             int oldHandle = passHandle;
2585             ObjectStreamField[] fields = desc.getFields(false);
2586             int numPrimFields = fields.length - objVals.length;
2587             for (int i = 0; i < objVals.length; i++) {
2588                 objVals[i] =
2589                     readObject0(Object.class, fields[numPrimFields + i].isUnshared());
2590                 objHandles[i] = passHandle;
2591             }
2592             passHandle = oldHandle;
2593         }
2594
2595         /**
2596          * Returns offset of field with given name and type.  A specified type
2597          * of null matches all types, Object.class matches all non-primitive
2598          * types, and any other non-null type matches assignable types only.
2599          * If no matching field is found in the (incoming) class
2600          * descriptor but a matching field is present in the associated local
2601          * class descriptor, returns -1.  Throws IllegalArgumentException if
2602          * neither incoming nor local class descriptor contains a match.
2603          */

2604         private int getFieldOffset(String name, Class<?> type) {
2605             ObjectStreamField field = desc.getField(name, type);
2606             if (field != null) {
2607                 return field.getOffset();
2608             } else if (desc.getLocalDesc().getField(name, type) != null) {
2609                 return -1;
2610             } else {
2611                 throw new IllegalArgumentException("no such field " + name +
2612                                                    " with type " + type);
2613             }
2614         }
2615     }
2616
2617     /**
2618      * Prioritized list of callbacks to be performed once object graph has been
2619      * completely deserialized.
2620      */

2621     private static class ValidationList {
2622
2623         private static class Callback {
2624             final ObjectInputValidation obj;
2625             final int priority;
2626             Callback next;
2627             final AccessControlContext acc;
2628
2629             Callback(ObjectInputValidation obj, int priority, Callback next,
2630                 AccessControlContext acc)
2631             {
2632                 this.obj = obj;
2633                 this.priority = priority;
2634                 this.next = next;
2635                 this.acc = acc;
2636             }
2637         }
2638
2639         /** linked list of callbacks */
2640         private Callback list;
2641
2642         /**
2643          * Creates new (empty) ValidationList.
2644          */

2645         ValidationList() {
2646         }
2647
2648         /**
2649          * Registers callback.  Throws InvalidObjectException if callback
2650          * object is null.
2651          */

2652         void register(ObjectInputValidation obj, int priority)
2653             throws InvalidObjectException
2654         {
2655             if (obj == null) {
2656                 throw new InvalidObjectException("null callback");
2657             }
2658
2659             Callback prev = null, cur = list;
2660             while (cur != null && priority < cur.priority) {
2661                 prev = cur;
2662                 cur = cur.next;
2663             }
2664             AccessControlContext acc = AccessController.getContext();
2665             if (prev != null) {
2666                 prev.next = new Callback(obj, priority, cur, acc);
2667             } else {
2668                 list = new Callback(obj, priority, list, acc);
2669             }
2670         }
2671
2672         /**
2673          * Invokes all registered callbacks and clears the callback list.
2674          * Callbacks with higher priorities are called first; those with equal
2675          * priorities may be called in any order.  If any of the callbacks
2676          * throws an InvalidObjectException, the callback process is terminated
2677          * and the exception propagated upwards.
2678          */

2679         void doCallbacks() throws InvalidObjectException {
2680             try {
2681                 while (list != null) {
2682                     AccessController.doPrivileged(
2683                         new PrivilegedExceptionAction<Void>()
2684                     {
2685                         public Void run() throws InvalidObjectException {
2686                             list.obj.validateObject();
2687                             return null;
2688                         }
2689                     }, list.acc);
2690                     list = list.next;
2691                 }
2692             } catch (PrivilegedActionException ex) {
2693                 list = null;
2694                 throw (InvalidObjectException) ex.getException();
2695             }
2696         }
2697
2698         /**
2699          * Resets the callback list to its initial (empty) state.
2700          */

2701         public void clear() {
2702             list = null;
2703         }
2704     }
2705
2706     /**
2707      * Hold a snapshot of values to be passed to an ObjectInputFilter.
2708      */

2709     static class FilterValues implements ObjectInputFilter.FilterInfo {
2710         final Class<?> clazz;
2711         final long arrayLength;
2712         final long totalObjectRefs;
2713         final long depth;
2714         final long streamBytes;
2715
2716         public FilterValues(Class<?> clazz, long arrayLength, long totalObjectRefs,
2717                             long depth, long streamBytes) {
2718             this.clazz = clazz;
2719             this.arrayLength = arrayLength;
2720             this.totalObjectRefs = totalObjectRefs;
2721             this.depth = depth;
2722             this.streamBytes = streamBytes;
2723         }
2724
2725         @Override
2726         public Class<?> serialClass() {
2727             return clazz;
2728         }
2729
2730         @Override
2731         public long arrayLength() {
2732             return arrayLength;
2733         }
2734
2735         @Override
2736         public long references() {
2737             return totalObjectRefs;
2738         }
2739
2740         @Override
2741         public long depth() {
2742             return depth;
2743         }
2744
2745         @Override
2746         public long streamBytes() {
2747             return streamBytes;
2748         }
2749     }
2750
2751     /**
2752      * Input stream supporting single-byte peek operations.
2753      */

2754     private static class PeekInputStream extends InputStream {
2755
2756         /** underlying stream */
2757         private final InputStream in;
2758         /** peeked byte */
2759         private int peekb = -1;
2760         /** total bytes read from the stream */
2761         private long totalBytesRead = 0;
2762
2763         /**
2764          * Creates new PeekInputStream on top of given underlying stream.
2765          */

2766         PeekInputStream(InputStream in) {
2767             this.in = in;
2768         }
2769
2770         /**
2771          * Peeks at next byte value in stream.  Similar to read(), except
2772          * that it does not consume the read value.
2773          */

2774         int peek() throws IOException {
2775             if (peekb >= 0) {
2776                 return peekb;
2777             }
2778             peekb = in.read();
2779             totalBytesRead += peekb >= 0 ? 1 : 0;
2780             return peekb;
2781         }
2782
2783         public int read() throws IOException {
2784             if (peekb >= 0) {
2785                 int v = peekb;
2786                 peekb = -1;
2787                 return v;
2788             } else {
2789                 int nbytes = in.read();
2790                 totalBytesRead += nbytes >= 0 ? 1 : 0;
2791                 return nbytes;
2792             }
2793         }
2794
2795         public int read(byte[] b, int off, int len) throws IOException {
2796             int nbytes;
2797             if (len == 0) {
2798                 return 0;
2799             } else if (peekb < 0) {
2800                 nbytes = in.read(b, off, len);
2801                 totalBytesRead += nbytes >= 0 ? nbytes : 0;
2802                 return nbytes;
2803             } else {
2804                 b[off++] = (byte) peekb;
2805                 len--;
2806                 peekb = -1;
2807                 nbytes = in.read(b, off, len);
2808                 totalBytesRead += nbytes >= 0 ? nbytes : 0;
2809                 return (nbytes >= 0) ? (nbytes + 1) : 1;
2810             }
2811         }
2812
2813         void readFully(byte[] b, int off, int len) throws IOException {
2814             int n = 0;
2815             while (n < len) {
2816                 int count = read(b, off + n, len - n);
2817                 if (count < 0) {
2818                     throw new EOFException();
2819                 }
2820                 n += count;
2821             }
2822         }
2823
2824         public long skip(long n) throws IOException {
2825             if (n <= 0) {
2826                 return 0;
2827             }
2828             int skipped = 0;
2829             if (peekb >= 0) {
2830                 peekb = -1;
2831                 skipped++;
2832                 n--;
2833             }
2834             n = skipped + in.skip(n);
2835             totalBytesRead += n;
2836             return n;
2837         }
2838
2839         public int available() throws IOException {
2840             return in.available() + ((peekb >= 0) ? 1 : 0);
2841         }
2842
2843         public void close() throws IOException {
2844             in.close();
2845         }
2846
2847         public long getBytesRead() {
2848             return totalBytesRead;
2849         }
2850     }
2851
2852     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
2853
2854     /**
2855      * Performs a "freeze" action, required to adhere to final field semantics.
2856      *
2857      * <p> This method can be called unconditionally before returning the graph,
2858      * from the topmost readObject call, since it is expected that the
2859      * additional cost of the freeze action is negligible compared to
2860      * reconstituting even the most simple graph.
2861      *
2862      * <p> Nested calls to readObject do not issue freeze actions because the
2863      * sub-graph returned from a nested call is not guaranteed to be fully
2864      * initialized yet (possible cycles).
2865      */

2866     private void freeze() {
2867         // Issue a StoreStore|StoreLoad fence, which is at least sufficient
2868         // to provide final-freeze semantics.
2869         UNSAFE.storeFence();
2870     }
2871
2872     /**
2873      * Input stream with two modes: in default mode, inputs data written in the
2874      * same format as DataOutputStream; in "block data" mode, inputs data
2875      * bracketed by block data markers (see object serialization specification
2876      * for details).  Buffering depends on block data mode: when in default
2877      * mode, no data is buffered in advance; when in block data mode, all data
2878      * for the current data block is read in at once (and buffered).
2879      */

2880     private class BlockDataInputStream
2881         extends InputStream implements DataInput
2882     {
2883         /** maximum data block length */
2884         private static final int MAX_BLOCK_SIZE = 1024;
2885         /** maximum data block header length */
2886         private static final int MAX_HEADER_SIZE = 5;
2887         /** (tunable) length of char buffer (for reading strings) */
2888         private static final int CHAR_BUF_SIZE = 256;
2889         /** readBlockHeader() return value indicating header read may block */
2890         private static final int HEADER_BLOCKED = -2;
2891
2892         /** buffer for reading general/block data */
2893         private final byte[] buf = new byte[MAX_BLOCK_SIZE];
2894         /** buffer for reading block data headers */
2895         private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
2896         /** char buffer for fast string reads */
2897         private final char[] cbuf = new char[CHAR_BUF_SIZE];
2898
2899         /** block data mode */
2900         private boolean blkmode = false;
2901
2902         // block data state fields; values meaningful only when blkmode true
2903         /** current offset into buf */
2904         private int pos = 0;
2905         /** end offset of valid data in buf, or -1 if no more block data */
2906         private int end = -1;
2907         /** number of bytes in current block yet to be read from stream */
2908         private int unread = 0;
2909
2910         /** underlying stream (wrapped in peekable filter stream) */
2911         private final PeekInputStream in;
2912         /** loopback stream (for data reads that span data blocks) */
2913         private final DataInputStream din;
2914
2915         /**
2916          * Creates new BlockDataInputStream on top of given underlying stream.
2917          * Block data mode is turned off by default.
2918          */

2919         BlockDataInputStream(InputStream in) {
2920             this.in = new PeekInputStream(in);
2921             din = new DataInputStream(this);
2922         }
2923
2924         /**
2925          * Sets block data mode to the given mode (true == on, false == off)
2926          * and returns the previous mode value.  If the new mode is the same as
2927          * the old mode, no action is taken.  Throws IllegalStateException if
2928          * block data mode is being switched from on to off while unconsumed
2929          * block data is still present in the stream.
2930          */

2931         boolean setBlockDataMode(boolean newmode) throws IOException {
2932             if (blkmode == newmode) {
2933                 return blkmode;
2934             }
2935             if (newmode) {
2936                 pos = 0;
2937                 end = 0;
2938                 unread = 0;
2939             } else if (pos < end) {
2940                 throw new IllegalStateException("unread block data");
2941             }
2942             blkmode = newmode;
2943             return !blkmode;
2944         }
2945
2946         /**
2947          * Returns true if the stream is currently in block data mode, false
2948          * otherwise.
2949          */

2950         boolean getBlockDataMode() {
2951             return blkmode;
2952         }
2953
2954         /**
2955          * If in block data mode, skips to the end of the current group of data
2956          * blocks (but does not unset block data mode).  If not in block data
2957          * mode, throws an IllegalStateException.
2958          */

2959         void skipBlockData() throws IOException {
2960             if (!blkmode) {
2961                 throw new IllegalStateException("not in block data mode");
2962             }
2963             while (end >= 0) {
2964                 refill();
2965             }
2966         }
2967
2968         /**
2969          * Attempts to read in the next block data header (if any).  If
2970          * canBlock is false and a full header cannot be read without possibly
2971          * blocking, returns HEADER_BLOCKED, else if the next element in the
2972          * stream is a block data header, returns the block data length
2973          * specified by the header, else returns -1.
2974          */

2975         private int readBlockHeader(boolean canBlock) throws IOException {
2976             if (defaultDataEnd) {
2977                 /*
2978                  * Fix for 4360508: stream is currently at the end of a field
2979                  * value block written via default serialization; since there
2980                  * is no terminating TC_ENDBLOCKDATA tag, simulate
2981                  * end-of-custom-data behavior explicitly.
2982                  */

2983                 return -1;
2984             }
2985             try {
2986                 for (;;) {
2987                     int avail = canBlock ? Integer.MAX_VALUE : in.available();
2988                     if (avail == 0) {
2989                         return HEADER_BLOCKED;
2990                     }
2991
2992                     int tc = in.peek();
2993                     switch (tc) {
2994                         case TC_BLOCKDATA:
2995                             if (avail < 2) {
2996                                 return HEADER_BLOCKED;
2997                             }
2998                             in.readFully(hbuf, 0, 2);
2999                             return hbuf[1] & 0xFF;
3000
3001                         case TC_BLOCKDATALONG:
3002                             if (avail < 5) {
3003                                 return HEADER_BLOCKED;
3004                             }
3005                             in.readFully(hbuf, 0, 5);
3006                             int len = Bits.getInt(hbuf, 1);
3007                             if (len < 0) {
3008                                 throw new StreamCorruptedException(
3009                                     "illegal block data header length: " +
3010                                     len);
3011                             }
3012                             return len;
3013
3014                         /*
3015                          * TC_RESETs may occur in between data blocks.
3016                          * Unfortunately, this case must be parsed at a lower
3017                          * level than other typecodes, since primitive data
3018                          * reads may span data blocks separated by a TC_RESET.
3019                          */

3020                         case TC_RESET:
3021                             in.read();
3022                             handleReset();
3023                             break;
3024
3025                         default:
3026                             if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
3027                                 throw new StreamCorruptedException(
3028                                     String.format("invalid type code: %02X",
3029                                     tc));
3030                             }
3031                             return -1;
3032                     }
3033                 }
3034             } catch (EOFException ex) {
3035                 throw new StreamCorruptedException(
3036                     "unexpected EOF while reading block data header");
3037             }
3038         }
3039
3040         /**
3041          * Refills internal buffer buf with block data.  Any data in buf at the
3042          * time of the call is considered consumed.  Sets the pos, end, and
3043          * unread fields to reflect the new amount of available block data; if
3044          * the next element in the stream is not a data block, sets pos and
3045          * unread to 0 and end to -1.
3046          */

3047         private void refill() throws IOException {
3048             try {
3049                 do {
3050                     pos = 0;
3051                     if (unread > 0) {
3052                         int n =
3053                             in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
3054                         if (n >= 0) {
3055                             end = n;
3056                             unread -= n;
3057                         } else {
3058                             throw new StreamCorruptedException(
3059                                 "unexpected EOF in middle of data block");
3060                         }
3061                     } else {
3062                         int n = readBlockHeader(true);
3063                         if (n >= 0) {
3064                             end = 0;
3065                             unread = n;
3066                         } else {
3067                             end = -1;
3068                             unread = 0;
3069                         }
3070                     }
3071                 } while (pos == end);
3072             } catch (IOException ex) {
3073                 pos = 0;
3074                 end = -1;
3075                 unread = 0;
3076                 throw ex;
3077             }
3078         }
3079
3080         /**
3081          * If in block data mode, returns the number of unconsumed bytes
3082          * remaining in the current data block.  If not in block data mode,
3083          * throws an IllegalStateException.
3084          */

3085         int currentBlockRemaining() {
3086             if (blkmode) {
3087                 return (end >= 0) ? (end - pos) + unread : 0;
3088             } else {
3089                 throw new IllegalStateException();
3090             }
3091         }
3092
3093         /**
3094          * Peeks at (but does not consume) and returns the next byte value in
3095          * the stream, or -1 if the end of the stream/block data (if in block
3096          * data mode) has been reached.
3097          */

3098         int peek() throws IOException {
3099             if (blkmode) {
3100                 if (pos == end) {
3101                     refill();
3102                 }
3103                 return (end >= 0) ? (buf[pos] & 0xFF) : -1;
3104             } else {
3105                 return in.peek();
3106             }
3107         }
3108
3109         /**
3110          * Peeks at (but does not consume) and returns the next byte value in
3111          * the stream, or throws EOFException if end of stream/block data has
3112          * been reached.
3113          */

3114         byte peekByte() throws IOException {
3115             int val = peek();
3116             if (val < 0) {
3117                 throw new EOFException();
3118             }
3119             return (byte) val;
3120         }
3121
3122
3123         /* ----------------- generic input stream methods ------------------ */
3124         /*
3125          * The following methods are equivalent to their counterparts in
3126          * InputStream, except that they interpret data block boundaries and
3127          * read the requested data from within data blocks when in block data
3128          * mode.
3129          */

3130
3131         public int read() throws IOException {
3132             if (blkmode) {
3133                 if (pos == end) {
3134                     refill();
3135                 }
3136                 return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
3137             } else {
3138                 return in.read();
3139             }
3140         }
3141
3142         public int read(byte[] b, int off, int len) throws IOException {
3143             return read(b, off, len, false);
3144         }
3145
3146         public long skip(long len) throws IOException {
3147             long remain = len;
3148             while (remain > 0) {
3149                 if (blkmode) {
3150                     if (pos == end) {
3151                         refill();
3152                     }
3153                     if (end < 0) {
3154                         break;
3155                     }
3156                     int nread = (int) Math.min(remain, end - pos);
3157                     remain -= nread;
3158                     pos += nread;
3159                 } else {
3160                     int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
3161                     if ((nread = in.read(buf, 0, nread)) < 0) {
3162                         break;
3163                     }
3164                     remain -= nread;
3165                 }
3166             }
3167             return len - remain;
3168         }
3169
3170         public int available() throws IOException {
3171             if (blkmode) {
3172                 if ((pos == end) && (unread == 0)) {
3173                     int n;
3174                     while ((n = readBlockHeader(false)) == 0) ;
3175                     switch (n) {
3176                         case HEADER_BLOCKED:
3177                             break;
3178
3179                         case -1:
3180                             pos = 0;
3181                             end = -1;
3182                             break;
3183
3184                         default:
3185                             pos = 0;
3186                             end = 0;
3187                             unread = n;
3188                             break;
3189                     }
3190                 }
3191                 // avoid unnecessary call to in.available() if possible
3192                 int unreadAvail = (unread > 0) ?
3193                     Math.min(in.available(), unread) : 0;
3194                 return (end >= 0) ? (end - pos) + unreadAvail : 0;
3195             } else {
3196                 return in.available();
3197             }
3198         }
3199
3200         public void close() throws IOException {
3201             if (blkmode) {
3202                 pos = 0;
3203                 end = -1;
3204                 unread = 0;
3205             }
3206             in.close();
3207         }
3208
3209         /**
3210          * Attempts to read len bytes into byte array b at offset off.  Returns
3211          * the number of bytes read, or -1 if the end of stream/block data has
3212          * been reached.  If copy is true, reads values into an intermediate
3213          * buffer before copying them to b (to avoid exposing a reference to
3214          * b).
3215          */

3216         int read(byte[] b, int off, int len, boolean copy) throws IOException {
3217             if (len == 0) {
3218                 return 0;
3219             } else if (blkmode) {
3220                 if (pos == end) {
3221                     refill();
3222                 }
3223                 if (end < 0) {
3224                     return -1;
3225                 }
3226                 int nread = Math.min(len, end - pos);
3227                 System.arraycopy(buf, pos, b, off, nread);
3228                 pos += nread;
3229                 return nread;
3230             } else if (copy) {
3231                 int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
3232                 if (nread > 0) {
3233                     System.arraycopy(buf, 0, b, off, nread);
3234                 }
3235                 return nread;
3236             } else {
3237                 return in.read(b, off, len);
3238             }
3239         }
3240
3241         /* ----------------- primitive data input methods ------------------ */
3242         /*
3243          * The following methods are equivalent to their counterparts in
3244          * DataInputStream, except that they interpret data block boundaries
3245          * and read the requested data from within data blocks when in block
3246          * data mode.
3247          */

3248
3249         public void readFully(byte[] b) throws IOException {
3250             readFully(b, 0, b.length, false);
3251         }
3252
3253         public void readFully(byte[] b, int off, int len) throws IOException {
3254             readFully(b, off, len, false);
3255         }
3256
3257         public void readFully(byte[] b, int off, int len, boolean copy)
3258             throws IOException
3259         {
3260             while (len > 0) {
3261                 int n = read(b, off, len, copy);
3262                 if (n < 0) {
3263                     throw new EOFException();
3264                 }
3265                 off += n;
3266                 len -= n;
3267             }
3268         }
3269
3270         public int skipBytes(int n) throws IOException {
3271             return din.skipBytes(n);
3272         }
3273
3274         public boolean readBoolean() throws IOException {
3275             int v = read();
3276             if (v < 0) {
3277                 throw new EOFException();
3278             }
3279             return (v != 0);
3280         }
3281
3282         public byte readByte() throws IOException {
3283             int v = read();
3284             if (v < 0) {
3285                 throw new EOFException();
3286             }
3287             return (byte) v;
3288         }
3289
3290         public int readUnsignedByte() throws IOException {
3291             int v = read();
3292             if (v < 0) {
3293                 throw new EOFException();
3294             }
3295             return v;
3296         }
3297
3298         public char readChar() throws IOException {
3299             if (!blkmode) {
3300                 pos = 0;
3301                 in.readFully(buf, 0, 2);
3302             } else if (end - pos < 2) {
3303                 return din.readChar();
3304             }
3305             char v = Bits.getChar(buf, pos);
3306             pos += 2;
3307             return v;
3308         }
3309
3310         public short readShort() throws IOException {
3311             if (!blkmode) {
3312                 pos = 0;
3313                 in.readFully(buf, 0, 2);
3314             } else if (end - pos < 2) {
3315                 return din.readShort();
3316             }
3317             short v = Bits.getShort(buf, pos);
3318             pos += 2;
3319             return v;
3320         }
3321
3322         public int readUnsignedShort() throws IOException {
3323             if (!blkmode) {
3324                 pos = 0;
3325                 in.readFully(buf, 0, 2);
3326             } else if (end - pos < 2) {
3327                 return din.readUnsignedShort();
3328             }
3329             int v = Bits.getShort(buf, pos) & 0xFFFF;
3330             pos += 2;
3331             return v;
3332         }
3333
3334         public int readInt() throws IOException {
3335             if (!blkmode) {
3336                 pos = 0;
3337                 in.readFully(buf, 0, 4);
3338             } else if (end - pos < 4) {
3339                 return din.readInt();
3340             }
3341             int v = Bits.getInt(buf, pos);
3342             pos += 4;
3343             return v;
3344         }
3345
3346         public float readFloat() throws IOException {
3347             if (!blkmode) {
3348                 pos = 0;
3349                 in.readFully(buf, 0, 4);
3350             } else if (end - pos < 4) {
3351                 return din.readFloat();
3352             }
3353             float v = Bits.getFloat(buf, pos);
3354             pos += 4;
3355             return v;
3356         }
3357
3358         public long readLong() throws IOException {
3359             if (!blkmode) {
3360                 pos = 0;
3361                 in.readFully(buf, 0, 8);
3362             } else if (end - pos < 8) {
3363                 return din.readLong();
3364             }
3365             long v = Bits.getLong(buf, pos);
3366             pos += 8;
3367             return v;
3368         }
3369
3370         public double readDouble() throws IOException {
3371             if (!blkmode) {
3372                 pos = 0;
3373                 in.readFully(buf, 0, 8);
3374             } else if (end - pos < 8) {
3375                 return din.readDouble();
3376             }
3377             double v = Bits.getDouble(buf, pos);
3378             pos += 8;
3379             return v;
3380         }
3381
3382         public String readUTF() throws IOException {
3383             return readUTFBody(readUnsignedShort());
3384         }
3385
3386         @SuppressWarnings("deprecation")
3387         public String readLine() throws IOException {
3388             return din.readLine();      // deprecated, not worth optimizing
3389         }
3390
3391         /* -------------- primitive data array input methods --------------- */
3392         /*
3393          * The following methods read in spans of primitive data values.
3394          * Though equivalent to calling the corresponding primitive read
3395          * methods repeatedly, these methods are optimized for reading groups
3396          * of primitive data values more efficiently.
3397          */

3398
3399         void readBooleans(boolean[] v, int off, int len) throws IOException {
3400             int stop, endoff = off + len;
3401             while (off < endoff) {
3402                 if (!blkmode) {
3403                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
3404                     in.readFully(buf, 0, span);
3405                     stop = off + span;
3406                     pos = 0;
3407                 } else if (end - pos < 1) {
3408                     v[off++] = din.readBoolean();
3409                     continue;
3410                 } else {
3411                     stop = Math.min(endoff, off + end - pos);
3412                 }
3413
3414                 while (off < stop) {
3415                     v[off++] = Bits.getBoolean(buf, pos++);
3416                 }
3417             }
3418         }
3419
3420         void readChars(char[] v, int off, int len) throws IOException {
3421             int stop, endoff = off + len;
3422             while (off < endoff) {
3423                 if (!blkmode) {
3424                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
3425                     in.readFully(buf, 0, span << 1);
3426                     stop = off + span;
3427                     pos = 0;
3428                 } else if (end - pos < 2) {
3429                     v[off++] = din.readChar();
3430                     continue;
3431                 } else {
3432                     stop = Math.min(endoff, off + ((end - pos) >> 1));
3433                 }
3434
3435                 while (off < stop) {
3436                     v[off++] = Bits.getChar(buf, pos);
3437                     pos += 2;
3438                 }
3439             }
3440         }
3441
3442         void readShorts(short[] v, int off, int len) throws IOException {
3443             int stop, endoff = off + len;
3444             while (off < endoff) {
3445                 if (!blkmode) {
3446                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
3447                     in.readFully(buf, 0, span << 1);
3448                     stop = off + span;
3449                     pos = 0;
3450                 } else if (end - pos < 2) {
3451                     v[off++] = din.readShort();
3452                     continue;
3453                 } else {
3454                     stop = Math.min(endoff, off + ((end - pos) >> 1));
3455                 }
3456
3457                 while (off < stop) {
3458                     v[off++] = Bits.getShort(buf, pos);
3459                     pos += 2;
3460                 }
3461             }
3462         }
3463
3464         void readInts(int[] v, int off, int len) throws IOException {
3465             int stop, endoff = off + len;
3466             while (off < endoff) {
3467                 if (!blkmode) {
3468                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
3469                     in.readFully(buf, 0, span << 2);
3470                     stop = off + span;
3471                     pos = 0;
3472                 } else if (end - pos < 4) {
3473                     v[off++] = din.readInt();
3474                     continue;
3475                 } else {
3476                     stop = Math.min(endoff, off + ((end - pos) >> 2));
3477                 }
3478
3479                 while (off < stop) {
3480                     v[off++] = Bits.getInt(buf, pos);
3481                     pos += 4;
3482                 }
3483             }
3484         }
3485
3486         void readFloats(float[] v, int off, int len) throws IOException {
3487             int span, endoff = off + len;
3488             while (off < endoff) {
3489                 if (!blkmode) {
3490                     span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
3491                     in.readFully(buf, 0, span << 2);
3492                     pos = 0;
3493                 } else if (end - pos < 4) {
3494                     v[off++] = din.readFloat();
3495                     continue;
3496                 } else {
3497                     span = Math.min(endoff - off, ((end - pos) >> 2));
3498                 }
3499
3500                 bytesToFloats(buf, pos, v, off, span);
3501                 off += span;
3502                 pos += span << 2;
3503             }
3504         }
3505
3506         void readLongs(long[] 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 >> 3);
3511                     in.readFully(buf, 0, span << 3);
3512                     stop = off + span;
3513                     pos = 0;
3514                 } else if (end - pos < 8) {
3515                     v[off++] = din.readLong();
3516                     continue;
3517                 } else {
3518                     stop = Math.min(endoff, off + ((end - pos) >> 3));
3519                 }
3520
3521                 while (off < stop) {
3522                     v[off++] = Bits.getLong(buf, pos);
3523                     pos += 8;
3524                 }
3525             }
3526         }
3527
3528         void readDoubles(double[] v, int off, int len) throws IOException {
3529             int span, endoff = off + len;
3530             while (off < endoff) {
3531                 if (!blkmode) {
3532                     span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
3533                     in.readFully(buf, 0, span << 3);
3534                     pos = 0;
3535                 } else if (end - pos < 8) {
3536                     v[off++] = din.readDouble();
3537                     continue;
3538                 } else {
3539                     span = Math.min(endoff - off, ((end - pos) >> 3));
3540                 }
3541
3542                 bytesToDoubles(buf, pos, v, off, span);
3543                 off += span;
3544                 pos += span << 3;
3545             }
3546         }
3547
3548         /**
3549          * Reads in string written in "long" UTF format.  "Long" UTF format is
3550          * identical to standard UTF, except that it uses an 8 byte header
3551          * (instead of the standard 2 bytes) to convey the UTF encoding length.
3552          */

3553         String readLongUTF() throws IOException {
3554             return readUTFBody(readLong());
3555         }
3556
3557         /**
3558          * Reads in the "body" (i.e., the UTF representation minus the 2-byte
3559          * or 8-byte length header) of a UTF encoding, which occupies the next
3560          * utflen bytes.
3561          */

3562         private String readUTFBody(long utflen) throws IOException {
3563             StringBuilder sbuf;
3564             if (utflen > 0 && utflen < Integer.MAX_VALUE) {
3565                 // a reasonable initial capacity based on the UTF length
3566                 int initialCapacity = Math.min((int)utflen, 0xFFFF);
3567                 sbuf = new StringBuilder(initialCapacity);
3568             } else {
3569                 sbuf = new StringBuilder();
3570             }
3571
3572             if (!blkmode) {
3573                 end = pos = 0;
3574             }
3575
3576             while (utflen > 0) {
3577                 int avail = end - pos;
3578                 if (avail >= 3 || (long) avail == utflen) {
3579                     utflen -= readUTFSpan(sbuf, utflen);
3580                 } else {
3581                     if (blkmode) {
3582                         // near block boundary, read one byte at a time
3583                         utflen -= readUTFChar(sbuf, utflen);
3584                     } else {
3585                         // shift and refill buffer manually
3586                         if (avail > 0) {
3587                             System.arraycopy(buf, pos, buf, 0, avail);
3588                         }
3589                         pos = 0;
3590                         end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
3591                         in.readFully(buf, avail, end - avail);
3592                     }
3593                 }
3594             }
3595
3596             return sbuf.toString();
3597         }
3598
3599         /**
3600          * Reads span of UTF-encoded characters out of internal buffer
3601          * (starting at offset pos and ending at or before offset end),
3602          * consuming no more than utflen bytes.  Appends read characters to
3603          * sbuf.  Returns the number of bytes consumed.
3604          */

3605         private long readUTFSpan(StringBuilder sbuf, long utflen)
3606             throws IOException
3607         {
3608             int cpos = 0;
3609             int start = pos;
3610             int avail = Math.min(end - pos, CHAR_BUF_SIZE);
3611             // stop short of last char unless all of utf bytes in buffer
3612             int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
3613             boolean outOfBounds = false;
3614
3615             try {
3616                 while (pos < stop) {
3617                     int b1, b2, b3;
3618                     b1 = buf[pos++] & 0xFF;
3619                     switch (b1 >> 4) {
3620                         case 0:
3621                         case 1:
3622                         case 2:
3623                         case 3:
3624                         case 4:
3625                         case 5:
3626                         case 6:
3627                         case 7:   // 1 byte format: 0xxxxxxx
3628                             cbuf[cpos++] = (char) b1;
3629                             break;
3630
3631                         case 12:
3632                         case 13:  // 2 byte format: 110xxxxx 10xxxxxx
3633                             b2 = buf[pos++];
3634                             if ((b2 & 0xC0) != 0x80) {
3635                                 throw new UTFDataFormatException();
3636                             }
3637                             cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
3638                                                    ((b2 & 0x3F) << 0));
3639                             break;
3640
3641                         case 14:  // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
3642                             b3 = buf[pos + 1];
3643                             b2 = buf[pos + 0];
3644                             pos += 2;
3645                             if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
3646                                 throw new UTFDataFormatException();
3647                             }
3648                             cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
3649                                                    ((b2 & 0x3F) << 6) |
3650                                                    ((b3 & 0x3F) << 0));
3651                             break;
3652
3653                         default:  // 10xx xxxx, 1111 xxxx
3654                             throw new UTFDataFormatException();
3655                     }
3656                 }
3657             } catch (ArrayIndexOutOfBoundsException ex) {
3658                 outOfBounds = true;
3659             } finally {
3660                 if (outOfBounds || (pos - start) > utflen) {
3661                     /*
3662                      * Fix for 4450867: if a malformed utf char causes the
3663                      * conversion loop to scan past the expected end of the utf
3664                      * string, only consume the expected number of utf bytes.
3665                      */

3666                     pos = start + (int) utflen;
3667                     throw new UTFDataFormatException();
3668                 }
3669             }
3670
3671             sbuf.append(cbuf, 0, cpos);
3672             return pos - start;
3673         }
3674
3675         /**
3676          * Reads in single UTF-encoded character one byte at a time, appends
3677          * the character to sbuf, and returns the number of bytes consumed.
3678          * This method is used when reading in UTF strings written in block
3679          * data mode to handle UTF-encoded characters which (potentially)
3680          * straddle block-data boundaries.
3681          */

3682         private int readUTFChar(StringBuilder sbuf, long utflen)
3683             throws IOException
3684         {
3685             int b1, b2, b3;
3686             b1 = readByte() & 0xFF;
3687             switch (b1 >> 4) {
3688                 case 0:
3689                 case 1:
3690                 case 2:
3691                 case 3:
3692                 case 4:
3693                 case 5:
3694                 case 6:
3695                 case 7:     // 1 byte format: 0xxxxxxx
3696                     sbuf.append((char) b1);
3697                     return 1;
3698
3699                 case 12:
3700                 case 13:    // 2 byte format: 110xxxxx 10xxxxxx
3701                     if (utflen < 2) {
3702                         throw new UTFDataFormatException();
3703                     }
3704                     b2 = readByte();
3705                     if ((b2 & 0xC0) != 0x80) {
3706                         throw new UTFDataFormatException();
3707                     }
3708                     sbuf.append((char) (((b1 & 0x1F) << 6) |
3709                                         ((b2 & 0x3F) << 0)));
3710                     return 2;
3711
3712                 case 14:    // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
3713                     if (utflen < 3) {
3714                         if (utflen == 2) {
3715                             readByte();         // consume remaining byte
3716                         }
3717                         throw new UTFDataFormatException();
3718                     }
3719                     b2 = readByte();
3720                     b3 = readByte();
3721                     if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
3722                         throw new UTFDataFormatException();
3723                     }
3724                     sbuf.append((char) (((b1 & 0x0F) << 12) |
3725                                         ((b2 & 0x3F) << 6) |
3726                                         ((b3 & 0x3F) << 0)));
3727                     return 3;
3728
3729                 default:   // 10xx xxxx, 1111 xxxx
3730                     throw new UTFDataFormatException();
3731             }
3732         }
3733
3734         /**
3735          * Returns the number of bytes read from the input stream.
3736          * @return the number of bytes read from the input stream
3737          */

3738         long getBytesRead() {
3739             return in.getBytesRead();
3740         }
3741     }
3742
3743     /**
3744      * Unsynchronized table which tracks wire handle to object mappings, as
3745      * well as ClassNotFoundExceptions associated with deserialized objects.
3746      * This class implements an exception-propagation algorithm for
3747      * determining which objects should have ClassNotFoundExceptions associated
3748      * with them, taking into account cycles and discontinuities (e.g., skipped
3749      * fields) in the object graph.
3750      *
3751      * <p>General use of the table is as follows: during deserialization, a
3752      * given object is first assigned a handle by calling the assign method.
3753      * This method leaves the assigned handle in an "open" state, wherein
3754      * dependencies on the exception status of other handles can be registered
3755      * by calling the markDependency method, or an exception can be directly
3756      * associated with the handle by calling markException.  When a handle is
3757      * tagged with an exception, the HandleTable assumes responsibility for
3758      * propagating the exception to any other objects which depend
3759      * (transitively) on the exception-tagged object.
3760      *
3761      * <p>Once all exception information/dependencies for the handle have been
3762      * registered, the handle should be "closed" by calling the finish method
3763      * on it.  The act of finishing a handle allows the exception propagation
3764      * algorithm to aggressively prune dependency links, lessening the
3765      * performance/memory impact of exception tracking.
3766      *
3767      * <p>Note that the exception propagation algorithm used depends on handles
3768      * being assigned/finished in LIFO order; however, for simplicity as well
3769      * as memory conservation, it does not enforce this constraint.
3770      */

3771     // REMIND: add full description of exception propagation algorithm?
3772     private static class HandleTable {
3773
3774         /* status codes indicating whether object has associated exception */
3775         private static final byte STATUS_OK = 1;
3776         private static final byte STATUS_UNKNOWN = 2;
3777         private static final byte STATUS_EXCEPTION = 3;
3778
3779         /** array mapping handle -> object status */
3780         byte[] status;
3781         /** array mapping handle -> object/exception (depending on status) */
3782         Object[] entries;
3783         /** array mapping handle -> list of dependent handles (if any) */
3784         HandleList[] deps;
3785         /** lowest unresolved dependency */
3786         int lowDep = -1;
3787         /** number of handles in table */
3788         int size = 0;
3789
3790         /**
3791          * Creates handle table with the given initial capacity.
3792          */

3793         HandleTable(int initialCapacity) {
3794             status = new byte[initialCapacity];
3795             entries = new Object[initialCapacity];
3796             deps = new HandleList[initialCapacity];
3797         }
3798
3799         /**
3800          * Assigns next available handle to given object, and returns assigned
3801          * handle.  Once object has been completely deserialized (and all
3802          * dependencies on other objects identified), the handle should be
3803          * "closed" by passing it to finish().
3804          */

3805         int assign(Object obj) {
3806             if (size >= entries.length) {
3807                 grow();
3808             }
3809             status[size] = STATUS_UNKNOWN;
3810             entries[size] = obj;
3811             return size++;
3812         }
3813
3814         /**
3815          * Registers a dependency (in exception status) of one handle on
3816          * another.  The dependent handle must be "open" (i.e., assigned, but
3817          * not finished yet).  No action is taken if either dependent or target
3818          * handle is NULL_HANDLE. Additionally, no action is taken if the
3819          * dependent and target are the same.
3820          */

3821         void markDependency(int dependent, int target) {
3822             if (dependent == target || dependent == NULL_HANDLE || target == NULL_HANDLE) {
3823                 return;
3824             }
3825             switch (status[dependent]) {
3826
3827                 case STATUS_UNKNOWN:
3828                     switch (status[target]) {
3829                         case STATUS_OK:
3830                             // ignore dependencies on objs with no exception
3831                             break;
3832
3833                         case STATUS_EXCEPTION:
3834                             // eagerly propagate exception
3835                             markException(dependent,
3836                                 (ClassNotFoundException) entries[target]);
3837                             break;
3838
3839                         case STATUS_UNKNOWN:
3840                             // add to dependency list of target
3841                             if (deps[target] == null) {
3842                                 deps[target] = new HandleList();
3843                             }
3844                             deps[target].add(dependent);
3845
3846                             // remember lowest unresolved target seen
3847                             if (lowDep < 0 || lowDep > target) {
3848                                 lowDep = target;
3849                             }
3850                             break;
3851
3852                         default:
3853                             throw new InternalError();
3854                     }
3855                     break;
3856
3857                 case STATUS_EXCEPTION:
3858                     break;
3859
3860                 default:
3861                     throw new InternalError();
3862             }
3863         }
3864
3865         /**
3866          * Associates a ClassNotFoundException (if one not already associated)
3867          * with the currently active handle and propagates it to other
3868          * referencing objects as appropriate.  The specified handle must be
3869          * "open" (i.e., assigned, but not finished yet).
3870          */

3871         void markException(int handle, ClassNotFoundException ex) {
3872             switch (status[handle]) {
3873                 case STATUS_UNKNOWN:
3874                     status[handle] = STATUS_EXCEPTION;
3875                     entries[handle] = ex;
3876
3877                     // propagate exception to dependents
3878                     HandleList dlist = deps[handle];
3879                     if (dlist != null) {
3880                         int ndeps = dlist.size();
3881                         for (int i = 0; i < ndeps; i++) {
3882                             markException(dlist.get(i), ex);
3883                         }
3884                         deps[handle] = null;
3885                     }
3886                     break;
3887
3888                 case STATUS_EXCEPTION:
3889                     break;
3890
3891                 default:
3892                     throw new InternalError();
3893             }
3894         }
3895
3896         /**
3897          * Marks given handle as finished, meaning that no new dependencies
3898          * will be marked for handle.  Calls to the assign and finish methods
3899          * must occur in LIFO order.
3900          */

3901         void finish(int handle) {
3902             int end;
3903             if (lowDep < 0) {
3904                 // no pending unknowns, only resolve current handle
3905                 end = handle + 1;
3906             } else if (lowDep >= handle) {
3907                 // pending unknowns now clearable, resolve all upward handles
3908                 end = size;
3909                 lowDep = -1;
3910             } else {
3911                 // unresolved backrefs present, can't resolve anything yet
3912                 return;
3913             }
3914
3915             // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
3916             for (int i = handle; i < end; i++) {
3917                 switch (status[i]) {
3918                     case STATUS_UNKNOWN:
3919                         status[i] = STATUS_OK;
3920                         deps[i] = null;
3921                         break;
3922
3923                     case STATUS_OK:
3924                     case STATUS_EXCEPTION:
3925                         break;
3926
3927                     default:
3928                         throw new InternalError();
3929                 }
3930             }
3931         }
3932
3933         /**
3934          * Assigns a new object to the given handle.  The object previously
3935          * associated with the handle is forgotten.  This method has no effect
3936          * if the given handle already has an exception associated with it.
3937          * This method may be called at any time after the handle is assigned.
3938          */

3939         void setObject(int handle, Object obj) {
3940             switch (status[handle]) {
3941                 case STATUS_UNKNOWN:
3942                 case STATUS_OK:
3943                     entries[handle] = obj;
3944                     break;
3945
3946                 case STATUS_EXCEPTION:
3947                     break;
3948
3949                 default:
3950                     throw new InternalError();
3951             }
3952         }
3953
3954         /**
3955          * Looks up and returns object associated with the given handle.
3956          * Returns null if the given handle is NULL_HANDLE, or if it has an
3957          * associated ClassNotFoundException.
3958          */

3959         Object lookupObject(int handle) {
3960             return (handle != NULL_HANDLE &&
3961                     status[handle] != STATUS_EXCEPTION) ?
3962                 entries[handle] : null;
3963         }
3964
3965         /**
3966          * Looks up and returns ClassNotFoundException associated with the
3967          * given handle.  Returns null if the given handle is NULL_HANDLE, or
3968          * if there is no ClassNotFoundException associated with the handle.
3969          */

3970         ClassNotFoundException lookupException(int handle) {
3971             return (handle != NULL_HANDLE &&
3972                     status[handle] == STATUS_EXCEPTION) ?
3973                 (ClassNotFoundException) entries[handle] : null;
3974         }
3975
3976         /**
3977          * Resets table to its initial state.
3978          */

3979         void clear() {
3980             Arrays.fill(status, 0, size, (byte) 0);
3981             Arrays.fill(entries, 0, size, null);
3982             Arrays.fill(deps, 0, size, null);
3983             lowDep = -1;
3984             size = 0;
3985         }
3986
3987         /**
3988          * Returns number of handles registered in table.
3989          */

3990         int size() {
3991             return size;
3992         }
3993
3994         /**
3995          * Expands capacity of internal arrays.
3996          */

3997         private void grow() {
3998             int newCapacity = (entries.length << 1) + 1;
3999
4000             byte[] newStatus = new byte[newCapacity];
4001             Object[] newEntries = new Object[newCapacity];
4002             HandleList[] newDeps = new HandleList[newCapacity];
4003
4004             System.arraycopy(status, 0, newStatus, 0, size);
4005             System.arraycopy(entries, 0, newEntries, 0, size);
4006             System.arraycopy(deps, 0, newDeps, 0, size);
4007
4008             status = newStatus;
4009             entries = newEntries;
4010             deps = newDeps;
4011         }
4012
4013         /**
4014          * Simple growable list of (integer) handles.
4015          */

4016         private static class HandleList {
4017             private int[] list = new int[4];
4018             private int size = 0;
4019
4020             public HandleList() {
4021             }
4022
4023             public void add(int handle) {
4024                 if (size >= list.length) {
4025                     int[] newList = new int[list.length << 1];
4026                     System.arraycopy(list, 0, newList, 0, list.length);
4027                     list = newList;
4028                 }
4029                 list[size++] = handle;
4030             }
4031
4032             public int get(int index) {
4033                 if (index >= size) {
4034                     throw new ArrayIndexOutOfBoundsException();
4035                 }
4036                 return list[index];
4037             }
4038
4039             public int size() {
4040                 return size;
4041             }
4042         }
4043     }
4044
4045     /**
4046      * Method for cloning arrays in case of using unsharing reading
4047      */

4048     private static Object cloneArray(Object array) {
4049         if (array instanceof Object[]) {
4050             return ((Object[]) array).clone();
4051         } else if (array instanceof boolean[]) {
4052             return ((boolean[]) array).clone();
4053         } else if (array instanceof byte[]) {
4054             return ((byte[]) array).clone();
4055         } else if (array instanceof char[]) {
4056             return ((char[]) array).clone();
4057         } else if (array instanceof double[]) {
4058             return ((double[]) array).clone();
4059         } else if (array instanceof float[]) {
4060             return ((float[]) array).clone();
4061         } else if (array instanceof int[]) {
4062             return ((int[]) array).clone();
4063         } else if (array instanceof long[]) {
4064             return ((long[]) array).clone();
4065         } else if (array instanceof short[]) {
4066             return ((short[]) array).clone();
4067         } else {
4068             throw new AssertionError();
4069         }
4070     }
4071
4072     static {
4073         SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::checkArray);
4074         SharedSecrets.setJavaObjectInputStreamReadString(ObjectInputStream::readString);
4075     }
4076
4077 }
4078