Path: blob/jdk8u272-b10-aarch32-20201026/jdk/src/share/classes/java/io/ObjectInputStream.java
83405 views
/*1* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.io;2627import java.io.ObjectStreamClass.WeakClassKey;28import java.lang.ref.ReferenceQueue;29import java.lang.reflect.Array;30import java.lang.reflect.InvocationHandler;31import java.lang.reflect.Modifier;32import java.lang.reflect.Proxy;33import java.security.AccessControlContext;34import java.security.AccessController;35import java.security.PrivilegedAction;36import java.security.PrivilegedActionException;37import java.security.PrivilegedExceptionAction;38import java.util.Arrays;39import java.util.HashMap;40import java.util.Objects;41import java.util.concurrent.ConcurrentHashMap;42import java.util.concurrent.ConcurrentMap;4344import static java.io.ObjectStreamClass.processQueue;4546import sun.misc.SharedSecrets;47import sun.misc.ObjectInputFilter;48import sun.misc.ObjectStreamClassValidator;49import sun.misc.SharedSecrets;50import sun.reflect.misc.ReflectUtil;51import sun.misc.JavaOISAccess;52import sun.util.logging.PlatformLogger;53import sun.security.action.GetBooleanAction;54import sun.security.action.GetIntegerAction;5556/**57* An ObjectInputStream deserializes primitive data and objects previously58* written using an ObjectOutputStream.59*60* <p>ObjectOutputStream and ObjectInputStream can provide an application with61* persistent storage for graphs of objects when used with a FileOutputStream62* and FileInputStream respectively. ObjectInputStream is used to recover63* those objects previously serialized. Other uses include passing objects64* between hosts using a socket stream or for marshaling and unmarshaling65* arguments and parameters in a remote communication system.66*67* <p>ObjectInputStream ensures that the types of all objects in the graph68* created from the stream match the classes present in the Java Virtual69* Machine. Classes are loaded as required using the standard mechanisms.70*71* <p>Only objects that support the java.io.Serializable or72* java.io.Externalizable interface can be read from streams.73*74* <p>The method <code>readObject</code> is used to read an object from the75* stream. Java's safe casting should be used to get the desired type. In76* Java, strings and arrays are objects and are treated as objects during77* serialization. When read they need to be cast to the expected type.78*79* <p>Primitive data types can be read from the stream using the appropriate80* method on DataInput.81*82* <p>The default deserialization mechanism for objects restores the contents83* of each field to the value and type it had when it was written. Fields84* declared as transient or static are ignored by the deserialization process.85* References to other objects cause those objects to be read from the stream86* as necessary. Graphs of objects are restored correctly using a reference87* sharing mechanism. New objects are always allocated when deserializing,88* which prevents existing objects from being overwritten.89*90* <p>Reading an object is analogous to running the constructors of a new91* object. Memory is allocated for the object and initialized to zero (NULL).92* No-arg constructors are invoked for the non-serializable classes and then93* the fields of the serializable classes are restored from the stream starting94* with the serializable class closest to java.lang.object and finishing with95* the object's most specific class.96*97* <p>For example to read from a stream as written by the example in98* ObjectOutputStream:99* <br>100* <pre>101* FileInputStream fis = new FileInputStream("t.tmp");102* ObjectInputStream ois = new ObjectInputStream(fis);103*104* int i = ois.readInt();105* String today = (String) ois.readObject();106* Date date = (Date) ois.readObject();107*108* ois.close();109* </pre>110*111* <p>Classes control how they are serialized by implementing either the112* java.io.Serializable or java.io.Externalizable interfaces.113*114* <p>Implementing the Serializable interface allows object serialization to115* save and restore the entire state of the object and it allows classes to116* evolve between the time the stream is written and the time it is read. It117* automatically traverses references between objects, saving and restoring118* entire graphs.119*120* <p>Serializable classes that require special handling during the121* serialization and deserialization process should implement the following122* methods:123*124* <pre>125* private void writeObject(java.io.ObjectOutputStream stream)126* throws IOException;127* private void readObject(java.io.ObjectInputStream stream)128* throws IOException, ClassNotFoundException;129* private void readObjectNoData()130* throws ObjectStreamException;131* </pre>132*133* <p>The readObject method is responsible for reading and restoring the state134* of the object for its particular class using data written to the stream by135* the corresponding writeObject method. The method does not need to concern136* itself with the state belonging to its superclasses or subclasses. State is137* restored by reading data from the ObjectInputStream for the individual138* fields and making assignments to the appropriate fields of the object.139* Reading primitive data types is supported by DataInput.140*141* <p>Any attempt to read object data which exceeds the boundaries of the142* custom data written by the corresponding writeObject method will cause an143* OptionalDataException to be thrown with an eof field value of true.144* Non-object reads which exceed the end of the allotted data will reflect the145* end of data in the same way that they would indicate the end of the stream:146* bytewise reads will return -1 as the byte read or number of bytes read, and147* primitive reads will throw EOFExceptions. If there is no corresponding148* writeObject method, then the end of default serialized data marks the end of149* the allotted data.150*151* <p>Primitive and object read calls issued from within a readExternal method152* behave in the same manner--if the stream is already positioned at the end of153* data written by the corresponding writeExternal method, object reads will154* throw OptionalDataExceptions with eof set to true, bytewise reads will155* return -1, and primitive reads will throw EOFExceptions. Note that this156* behavior does not hold for streams written with the old157* <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the158* end of data written by writeExternal methods is not demarcated, and hence159* cannot be detected.160*161* <p>The readObjectNoData method is responsible for initializing the state of162* the object for its particular class in the event that the serialization163* stream does not list the given class as a superclass of the object being164* deserialized. This may occur in cases where the receiving party uses a165* different version of the deserialized instance's class than the sending166* party, and the receiver's version extends classes that are not extended by167* the sender's version. This may also occur if the serialization stream has168* been tampered; hence, readObjectNoData is useful for initializing169* deserialized objects properly despite a "hostile" or incomplete source170* stream.171*172* <p>Serialization does not read or assign values to the fields of any object173* that does not implement the java.io.Serializable interface. Subclasses of174* Objects that are not serializable can be serializable. In this case the175* non-serializable class must have a no-arg constructor to allow its fields to176* be initialized. In this case it is the responsibility of the subclass to177* save and restore the state of the non-serializable class. It is frequently178* the case that the fields of that class are accessible (public, package, or179* protected) or that there are get and set methods that can be used to restore180* the state.181*182* <p>Any exception that occurs while deserializing an object will be caught by183* the ObjectInputStream and abort the reading process.184*185* <p>Implementing the Externalizable interface allows the object to assume186* complete control over the contents and format of the object's serialized187* form. The methods of the Externalizable interface, writeExternal and188* readExternal, are called to save and restore the objects state. When189* implemented by a class they can write and read their own state using all of190* the methods of ObjectOutput and ObjectInput. It is the responsibility of191* the objects to handle any versioning that occurs.192*193* <p>Enum constants are deserialized differently than ordinary serializable or194* externalizable objects. The serialized form of an enum constant consists195* solely of its name; field values of the constant are not transmitted. To196* deserialize an enum constant, ObjectInputStream reads the constant name from197* the stream; the deserialized constant is then obtained by calling the static198* method <code>Enum.valueOf(Class, String)</code> with the enum constant's199* base type and the received constant name as arguments. Like other200* serializable or externalizable objects, enum constants can function as the201* targets of back references appearing subsequently in the serialization202* stream. The process by which enum constants are deserialized cannot be203* customized: any class-specific readObject, readObjectNoData, and readResolve204* methods defined by enum types are ignored during deserialization.205* Similarly, any serialPersistentFields or serialVersionUID field declarations206* are also ignored--all enum types have a fixed serialVersionUID of 0L.207*208* @author Mike Warres209* @author Roger Riggs210* @see java.io.DataInput211* @see java.io.ObjectOutputStream212* @see java.io.Serializable213* @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>214* @since JDK1.1215*/216public class ObjectInputStream217extends InputStream implements ObjectInput, ObjectStreamConstants218{219/** handle value representing null */220private static final int NULL_HANDLE = -1;221222/** marker for unshared objects in internal handle table */223private static final Object unsharedMarker = new Object();224225/** table mapping primitive type names to corresponding class objects */226private static final HashMap<String, Class<?>> primClasses227= new HashMap<>(8, 1.0F);228static {229primClasses.put("boolean", boolean.class);230primClasses.put("byte", byte.class);231primClasses.put("char", char.class);232primClasses.put("short", short.class);233primClasses.put("int", int.class);234primClasses.put("long", long.class);235primClasses.put("float", float.class);236primClasses.put("double", double.class);237primClasses.put("void", void.class);238}239240private static class Caches {241/** cache of subclass security audit results */242static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =243new ConcurrentHashMap<>();244245/** queue for WeakReferences to audited subclasses */246static final ReferenceQueue<Class<?>> subclassAuditsQueue =247new ReferenceQueue<>();248249/**250* Property to permit setting a filter after objects251* have been read.252* See {@link #setObjectInputFilter(ObjectInputFilter)}253*/254static final boolean SET_FILTER_AFTER_READ =255privilegedGetProperty("jdk.serialSetFilterAfterRead");256257/**258* Property to override the implementation limit on the number259* of interfaces allowed for Proxies. The property value is clamped to 0..65535.260* The maximum number of interfaces allowed for a proxy is limited to 65535 by261* {@link java.lang.reflect.Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)}262*/263static final int PROXY_INTERFACE_LIMIT = Math.max(0, Math.min(65535,264privilegedGetIntegerProperty("jdk.serialProxyInterfaceLimit", 65535)));265266private static boolean privilegedGetProperty(String theProp) {267if (System.getSecurityManager() == null) {268return Boolean.getBoolean(theProp);269} else {270return AccessController.doPrivileged(271new GetBooleanAction(theProp));272}273}274275private static int privilegedGetIntegerProperty(String theProp, int defaultValue) {276if (System.getSecurityManager() == null) {277return Integer.getInteger(theProp, defaultValue);278} else {279return AccessController.doPrivileged(280new GetIntegerAction(theProp, defaultValue));281}282}283}284285static {286/* Setup access so sun.misc can invoke package private functions. */287JavaOISAccess javaOISAccess = new JavaOISAccess() {288public void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter) {289stream.setInternalObjectInputFilter(filter);290}291292public ObjectInputFilter getObjectInputFilter(ObjectInputStream stream) {293return stream.getInternalObjectInputFilter();294}295296public void checkArray(ObjectInputStream stream, Class<?> arrayType, int arrayLength)297throws InvalidClassException298{299stream.checkArray(arrayType, arrayLength);300}301};302303sun.misc.SharedSecrets.setJavaOISAccess(javaOISAccess);304}305306/*307* Separate class to defer initialization of logging until needed.308*/309private static class Logging {310311/*312* Logger for ObjectInputFilter results.313* Setup the filter logger if it is set to INFO or WARNING.314* (Assuming it will not change).315*/316private static final PlatformLogger traceLogger;317private static final PlatformLogger infoLogger;318static {319PlatformLogger filterLog = PlatformLogger.getLogger("java.io.serialization");320infoLogger = (filterLog != null &&321filterLog.isLoggable(PlatformLogger.Level.INFO)) ? filterLog : null;322traceLogger = (filterLog != null &&323filterLog.isLoggable(PlatformLogger.Level.FINER)) ? filterLog : null;324}325}326327/** filter stream for handling block data conversion */328private final BlockDataInputStream bin;329/** validation callback list */330private final ValidationList vlist;331/** recursion depth */332private long depth;333/** Total number of references to any type of object, class, enum, proxy, etc. */334private long totalObjectRefs;335/** whether stream is closed */336private boolean closed;337338/** wire handle -> obj/exception map */339private final HandleTable handles;340/** scratch field for passing handle values up/down call stack */341private int passHandle = NULL_HANDLE;342/** flag set when at end of field value block with no TC_ENDBLOCKDATA */343private boolean defaultDataEnd = false;344345/** buffer for reading primitive field values */346private byte[] primVals;347348/** if true, invoke readObjectOverride() instead of readObject() */349private final boolean enableOverride;350/** if true, invoke resolveObject() */351private boolean enableResolve;352353/**354* Context during upcalls to class-defined readObject methods; holds355* object currently being deserialized and descriptor for current class.356* Null when not during readObject upcall.357*/358private SerialCallbackContext curContext;359360/**361* Filter of class descriptors and classes read from the stream;362* may be null.363*/364private ObjectInputFilter serialFilter;365366/**367* Creates an ObjectInputStream that reads from the specified InputStream.368* A serialization stream header is read from the stream and verified.369* This constructor will block until the corresponding ObjectOutputStream370* has written and flushed the header.371*372* <p>If a security manager is installed, this constructor will check for373* the "enableSubclassImplementation" SerializablePermission when invoked374* directly or indirectly by the constructor of a subclass which overrides375* the ObjectInputStream.readFields or ObjectInputStream.readUnshared376* methods.377*378* @param in input stream to read from379* @throws StreamCorruptedException if the stream header is incorrect380* @throws IOException if an I/O error occurs while reading stream header381* @throws SecurityException if untrusted subclass illegally overrides382* security-sensitive methods383* @throws NullPointerException if <code>in</code> is <code>null</code>384* @see ObjectInputStream#ObjectInputStream()385* @see ObjectInputStream#readFields()386* @see ObjectOutputStream#ObjectOutputStream(OutputStream)387*/388public ObjectInputStream(InputStream in) throws IOException {389verifySubclass();390bin = new BlockDataInputStream(in);391handles = new HandleTable(10);392vlist = new ValidationList();393serialFilter = ObjectInputFilter.Config.getSerialFilter();394enableOverride = false;395readStreamHeader();396bin.setBlockDataMode(true);397}398399/**400* Provide a way for subclasses that are completely reimplementing401* ObjectInputStream to not have to allocate private data just used by this402* implementation of ObjectInputStream.403*404* <p>If there is a security manager installed, this method first calls the405* security manager's <code>checkPermission</code> method with the406* <code>SerializablePermission("enableSubclassImplementation")</code>407* permission to ensure it's ok to enable subclassing.408*409* @throws SecurityException if a security manager exists and its410* <code>checkPermission</code> method denies enabling411* subclassing.412* @throws IOException if an I/O error occurs while creating this stream413* @see SecurityManager#checkPermission414* @see java.io.SerializablePermission415*/416protected ObjectInputStream() throws IOException, SecurityException {417SecurityManager sm = System.getSecurityManager();418if (sm != null) {419sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);420}421bin = null;422handles = null;423vlist = null;424serialFilter = ObjectInputFilter.Config.getSerialFilter();425enableOverride = true;426}427428/**429* Read an object from the ObjectInputStream. The class of the object, the430* signature of the class, and the values of the non-transient and431* non-static fields of the class and all of its supertypes are read.432* Default deserializing for a class can be overridden using the writeObject433* and readObject methods. Objects referenced by this object are read434* transitively so that a complete equivalent graph of objects is435* reconstructed by readObject.436*437* <p>The root object is completely restored when all of its fields and the438* objects it references are completely restored. At this point the object439* validation callbacks are executed in order based on their registered440* priorities. The callbacks are registered by objects (in the readObject441* special methods) as they are individually restored.442*443* <p>Exceptions are thrown for problems with the InputStream and for444* classes that should not be deserialized. All exceptions are fatal to445* the InputStream and leave it in an indeterminate state; it is up to the446* caller to ignore or recover the stream state.447*448* @throws ClassNotFoundException Class of a serialized object cannot be449* found.450* @throws InvalidClassException Something is wrong with a class used by451* serialization.452* @throws StreamCorruptedException Control information in the453* stream is inconsistent.454* @throws OptionalDataException Primitive data was found in the455* stream instead of objects.456* @throws IOException Any of the usual Input/Output related exceptions.457*/458public final Object readObject()459throws IOException, ClassNotFoundException {460return readObject(Object.class);461}462463/**464* Reads a String and only a string.465*466* @return the String read467* @throws EOFException If end of file is reached.468* @throws IOException If other I/O error has occurred.469*/470private String readString() throws IOException {471try {472return (String) readObject(String.class);473} catch (ClassNotFoundException cnf) {474throw new IllegalStateException(cnf);475}476}477478/**479* Internal method to read an object from the ObjectInputStream of the expected type.480* Called only from {@code readObject()} and {@code readString()}.481* Only {@code Object.class} and {@code String.class} are supported.482*483* @param type the type expected; either Object.class or String.class484* @return an object of the type485* @throws IOException Any of the usual Input/Output related exceptions.486* @throws ClassNotFoundException Class of a serialized object cannot be487* found.488*/489private final Object readObject(Class<?> type)490throws IOException, ClassNotFoundException491{492if (enableOverride) {493return readObjectOverride();494}495496if (! (type == Object.class || type == String.class))497throw new AssertionError("internal error");498499// if nested read, passHandle contains handle of enclosing object500int outerHandle = passHandle;501try {502Object obj = readObject0(type, false);503handles.markDependency(outerHandle, passHandle);504ClassNotFoundException ex = handles.lookupException(passHandle);505if (ex != null) {506throw ex;507}508if (depth == 0) {509vlist.doCallbacks();510}511return obj;512} finally {513passHandle = outerHandle;514if (closed && depth == 0) {515clear();516}517}518}519520/**521* This method is called by trusted subclasses of ObjectOutputStream that522* constructed ObjectOutputStream using the protected no-arg constructor.523* The subclass is expected to provide an override method with the modifier524* "final".525*526* @return the Object read from the stream.527* @throws ClassNotFoundException Class definition of a serialized object528* cannot be found.529* @throws OptionalDataException Primitive data was found in the stream530* instead of objects.531* @throws IOException if I/O errors occurred while reading from the532* underlying stream533* @see #ObjectInputStream()534* @see #readObject()535* @since 1.2536*/537protected Object readObjectOverride()538throws IOException, ClassNotFoundException539{540return null;541}542543/**544* Reads an "unshared" object from the ObjectInputStream. This method is545* identical to readObject, except that it prevents subsequent calls to546* readObject and readUnshared from returning additional references to the547* deserialized instance obtained via this call. Specifically:548* <ul>549* <li>If readUnshared is called to deserialize a back-reference (the550* stream representation of an object which has been written551* previously to the stream), an ObjectStreamException will be552* thrown.553*554* <li>If readUnshared returns successfully, then any subsequent attempts555* to deserialize back-references to the stream handle deserialized556* by readUnshared will cause an ObjectStreamException to be thrown.557* </ul>558* Deserializing an object via readUnshared invalidates the stream handle559* associated with the returned object. Note that this in itself does not560* always guarantee that the reference returned by readUnshared is unique;561* the deserialized object may define a readResolve method which returns an562* object visible to other parties, or readUnshared may return a Class563* object or enum constant obtainable elsewhere in the stream or through564* external means. If the deserialized object defines a readResolve method565* and the invocation of that method returns an array, then readUnshared566* returns a shallow clone of that array; this guarantees that the returned567* array object is unique and cannot be obtained a second time from an568* invocation of readObject or readUnshared on the ObjectInputStream,569* even if the underlying data stream has been manipulated.570*571* <p>ObjectInputStream subclasses which override this method can only be572* constructed in security contexts possessing the573* "enableSubclassImplementation" SerializablePermission; any attempt to574* instantiate such a subclass without this permission will cause a575* SecurityException to be thrown.576*577* @return reference to deserialized object578* @throws ClassNotFoundException if class of an object to deserialize579* cannot be found580* @throws StreamCorruptedException if control information in the stream581* is inconsistent582* @throws ObjectStreamException if object to deserialize has already583* appeared in stream584* @throws OptionalDataException if primitive data is next in stream585* @throws IOException if an I/O error occurs during deserialization586* @since 1.4587*/588public Object readUnshared() throws IOException, ClassNotFoundException {589// if nested read, passHandle contains handle of enclosing object590int outerHandle = passHandle;591try {592Object obj = readObject0(Object.class, true);593handles.markDependency(outerHandle, passHandle);594ClassNotFoundException ex = handles.lookupException(passHandle);595if (ex != null) {596throw ex;597}598if (depth == 0) {599vlist.doCallbacks();600}601return obj;602} finally {603passHandle = outerHandle;604if (closed && depth == 0) {605clear();606}607}608}609610/**611* Read the non-static and non-transient fields of the current class from612* this stream. This may only be called from the readObject method of the613* class being deserialized. It will throw the NotActiveException if it is614* called otherwise.615*616* @throws ClassNotFoundException if the class of a serialized object617* could not be found.618* @throws IOException if an I/O error occurs.619* @throws NotActiveException if the stream is not currently reading620* objects.621*/622public void defaultReadObject()623throws IOException, ClassNotFoundException624{625SerialCallbackContext ctx = curContext;626if (ctx == null) {627throw new NotActiveException("not in call to readObject");628}629Object curObj = ctx.getObj();630ObjectStreamClass curDesc = ctx.getDesc();631bin.setBlockDataMode(false);632defaultReadFields(curObj, curDesc);633bin.setBlockDataMode(true);634if (!curDesc.hasWriteObjectData()) {635/*636* Fix for 4360508: since stream does not contain terminating637* TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere638* knows to simulate end-of-custom-data behavior.639*/640defaultDataEnd = true;641}642ClassNotFoundException ex = handles.lookupException(passHandle);643if (ex != null) {644throw ex;645}646}647648/**649* Reads the persistent fields from the stream and makes them available by650* name.651*652* @return the <code>GetField</code> object representing the persistent653* fields of the object being deserialized654* @throws ClassNotFoundException if the class of a serialized object655* could not be found.656* @throws IOException if an I/O error occurs.657* @throws NotActiveException if the stream is not currently reading658* objects.659* @since 1.2660*/661public ObjectInputStream.GetField readFields()662throws IOException, ClassNotFoundException663{664SerialCallbackContext ctx = curContext;665if (ctx == null) {666throw new NotActiveException("not in call to readObject");667}668Object curObj = ctx.getObj();669ObjectStreamClass curDesc = ctx.getDesc();670bin.setBlockDataMode(false);671GetFieldImpl getField = new GetFieldImpl(curDesc);672getField.readFields();673bin.setBlockDataMode(true);674if (!curDesc.hasWriteObjectData()) {675/*676* Fix for 4360508: since stream does not contain terminating677* TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere678* knows to simulate end-of-custom-data behavior.679*/680defaultDataEnd = true;681}682683return getField;684}685686/**687* Register an object to be validated before the graph is returned. While688* similar to resolveObject these validations are called after the entire689* graph has been reconstituted. Typically, a readObject method will690* register the object with the stream so that when all of the objects are691* restored a final set of validations can be performed.692*693* @param obj the object to receive the validation callback.694* @param prio controls the order of callbacks;zero is a good default.695* Use higher numbers to be called back earlier, lower numbers for696* later callbacks. Within a priority, callbacks are processed in697* no particular order.698* @throws NotActiveException The stream is not currently reading objects699* so it is invalid to register a callback.700* @throws InvalidObjectException The validation object is null.701*/702public void registerValidation(ObjectInputValidation obj, int prio)703throws NotActiveException, InvalidObjectException704{705if (depth == 0) {706throw new NotActiveException("stream inactive");707}708vlist.register(obj, prio);709}710711/**712* Load the local class equivalent of the specified stream class713* description. Subclasses may implement this method to allow classes to714* be fetched from an alternate source.715*716* <p>The corresponding method in <code>ObjectOutputStream</code> is717* <code>annotateClass</code>. This method will be invoked only once for718* each unique class in the stream. This method can be implemented by719* subclasses to use an alternate loading mechanism but must return a720* <code>Class</code> object. Once returned, if the class is not an array721* class, its serialVersionUID is compared to the serialVersionUID of the722* serialized class, and if there is a mismatch, the deserialization fails723* and an {@link InvalidClassException} is thrown.724*725* <p>The default implementation of this method in726* <code>ObjectInputStream</code> returns the result of calling727* <pre>728* Class.forName(desc.getName(), false, loader)729* </pre>730* where <code>loader</code> is determined as follows: if there is a731* method on the current thread's stack whose declaring class was732* defined by a user-defined class loader (and was not a generated to733* implement reflective invocations), then <code>loader</code> is class734* loader corresponding to the closest such method to the currently735* executing frame; otherwise, <code>loader</code> is736* <code>null</code>. If this call results in a737* <code>ClassNotFoundException</code> and the name of the passed738* <code>ObjectStreamClass</code> instance is the Java language keyword739* for a primitive type or void, then the <code>Class</code> object740* representing that primitive type or void will be returned741* (e.g., an <code>ObjectStreamClass</code> with the name742* <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).743* Otherwise, the <code>ClassNotFoundException</code> will be thrown to744* the caller of this method.745*746* @param desc an instance of class <code>ObjectStreamClass</code>747* @return a <code>Class</code> object corresponding to <code>desc</code>748* @throws IOException any of the usual Input/Output exceptions.749* @throws ClassNotFoundException if class of a serialized object cannot750* be found.751*/752protected Class<?> resolveClass(ObjectStreamClass desc)753throws IOException, ClassNotFoundException754{755String name = desc.getName();756try {757return Class.forName(name, false, latestUserDefinedLoader());758} catch (ClassNotFoundException ex) {759Class<?> cl = primClasses.get(name);760if (cl != null) {761return cl;762} else {763throw ex;764}765}766}767768/**769* Returns a proxy class that implements the interfaces named in a proxy770* class descriptor; subclasses may implement this method to read custom771* data from the stream along with the descriptors for dynamic proxy772* classes, allowing them to use an alternate loading mechanism for the773* interfaces and the proxy class.774*775* <p>This method is called exactly once for each unique proxy class776* descriptor in the stream.777*778* <p>The corresponding method in <code>ObjectOutputStream</code> is779* <code>annotateProxyClass</code>. For a given subclass of780* <code>ObjectInputStream</code> that overrides this method, the781* <code>annotateProxyClass</code> method in the corresponding subclass of782* <code>ObjectOutputStream</code> must write any data or objects read by783* this method.784*785* <p>The default implementation of this method in786* <code>ObjectInputStream</code> returns the result of calling787* <code>Proxy.getProxyClass</code> with the list of <code>Class</code>788* objects for the interfaces that are named in the <code>interfaces</code>789* parameter. The <code>Class</code> object for each interface name790* <code>i</code> is the value returned by calling791* <pre>792* Class.forName(i, false, loader)793* </pre>794* where <code>loader</code> is that of the first non-<code>null</code>795* class loader up the execution stack, or <code>null</code> if no796* non-<code>null</code> class loaders are on the stack (the same class797* loader choice used by the <code>resolveClass</code> method). Unless any798* of the resolved interfaces are non-public, this same value of799* <code>loader</code> is also the class loader passed to800* <code>Proxy.getProxyClass</code>; if non-public interfaces are present,801* their class loader is passed instead (if more than one non-public802* interface class loader is encountered, an803* <code>IllegalAccessError</code> is thrown).804* If <code>Proxy.getProxyClass</code> throws an805* <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>806* will throw a <code>ClassNotFoundException</code> containing the807* <code>IllegalArgumentException</code>.808*809* @param interfaces the list of interface names that were810* deserialized in the proxy class descriptor811* @return a proxy class for the specified interfaces812* @throws IOException any exception thrown by the underlying813* <code>InputStream</code>814* @throws ClassNotFoundException if the proxy class or any of the815* named interfaces could not be found816* @see ObjectOutputStream#annotateProxyClass(Class)817* @since 1.3818*/819protected Class<?> resolveProxyClass(String[] interfaces)820throws IOException, ClassNotFoundException821{822ClassLoader latestLoader = latestUserDefinedLoader();823ClassLoader nonPublicLoader = null;824boolean hasNonPublicInterface = false;825826// define proxy in class loader of non-public interface(s), if any827Class<?>[] classObjs = new Class<?>[interfaces.length];828for (int i = 0; i < interfaces.length; i++) {829Class<?> cl = Class.forName(interfaces[i], false, latestLoader);830if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {831if (hasNonPublicInterface) {832if (nonPublicLoader != cl.getClassLoader()) {833throw new IllegalAccessError(834"conflicting non-public interface class loaders");835}836} else {837nonPublicLoader = cl.getClassLoader();838hasNonPublicInterface = true;839}840}841classObjs[i] = cl;842}843try {844return Proxy.getProxyClass(845hasNonPublicInterface ? nonPublicLoader : latestLoader,846classObjs);847} catch (IllegalArgumentException e) {848throw new ClassNotFoundException(null, e);849}850}851852/**853* This method will allow trusted subclasses of ObjectInputStream to854* substitute one object for another during deserialization. Replacing855* objects is disabled until enableResolveObject is called. The856* enableResolveObject method checks that the stream requesting to resolve857* object can be trusted. Every reference to serializable objects is passed858* to resolveObject. To insure that the private state of objects is not859* unintentionally exposed only trusted streams may use resolveObject.860*861* <p>This method is called after an object has been read but before it is862* returned from readObject. The default resolveObject method just returns863* the same object.864*865* <p>When a subclass is replacing objects it must insure that the866* substituted object is compatible with every field where the reference867* will be stored. Objects whose type is not a subclass of the type of the868* field or array element abort the serialization by raising an exception869* and the object is not be stored.870*871* <p>This method is called only once when each object is first872* encountered. All subsequent references to the object will be redirected873* to the new object.874*875* @param obj object to be substituted876* @return the substituted object877* @throws IOException Any of the usual Input/Output exceptions.878*/879protected Object resolveObject(Object obj) throws IOException {880return obj;881}882883/**884* Enable the stream to allow objects read from the stream to be replaced.885* When enabled, the resolveObject method is called for every object being886* deserialized.887*888* <p>If <i>enable</i> is true, and there is a security manager installed,889* this method first calls the security manager's890* <code>checkPermission</code> method with the891* <code>SerializablePermission("enableSubstitution")</code> permission to892* ensure it's ok to enable the stream to allow objects read from the893* stream to be replaced.894*895* @param enable true for enabling use of <code>resolveObject</code> for896* every object being deserialized897* @return the previous setting before this method was invoked898* @throws SecurityException if a security manager exists and its899* <code>checkPermission</code> method denies enabling the stream900* to allow objects read from the stream to be replaced.901* @see SecurityManager#checkPermission902* @see java.io.SerializablePermission903*/904protected boolean enableResolveObject(boolean enable)905throws SecurityException906{907if (enable == enableResolve) {908return enable;909}910if (enable) {911SecurityManager sm = System.getSecurityManager();912if (sm != null) {913sm.checkPermission(SUBSTITUTION_PERMISSION);914}915}916enableResolve = enable;917return !enableResolve;918}919920/**921* The readStreamHeader method is provided to allow subclasses to read and922* verify their own stream headers. It reads and verifies the magic number923* and version number.924*925* @throws IOException if there are I/O errors while reading from the926* underlying <code>InputStream</code>927* @throws StreamCorruptedException if control information in the stream928* is inconsistent929*/930protected void readStreamHeader()931throws IOException, StreamCorruptedException932{933short s0 = bin.readShort();934short s1 = bin.readShort();935if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {936throw new StreamCorruptedException(937String.format("invalid stream header: %04X%04X", s0, s1));938}939}940941/**942* Read a class descriptor from the serialization stream. This method is943* called when the ObjectInputStream expects a class descriptor as the next944* item in the serialization stream. Subclasses of ObjectInputStream may945* override this method to read in class descriptors that have been written946* in non-standard formats (by subclasses of ObjectOutputStream which have947* overridden the <code>writeClassDescriptor</code> method). By default,948* this method reads class descriptors according to the format defined in949* the Object Serialization specification.950*951* @return the class descriptor read952* @throws IOException If an I/O error has occurred.953* @throws ClassNotFoundException If the Class of a serialized object used954* in the class descriptor representation cannot be found955* @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)956* @since 1.3957*/958protected ObjectStreamClass readClassDescriptor()959throws IOException, ClassNotFoundException960{961ObjectStreamClass desc = new ObjectStreamClass();962desc.readNonProxy(this);963return desc;964}965966/**967* Reads a byte of data. This method will block if no input is available.968*969* @return the byte read, or -1 if the end of the stream is reached.970* @throws IOException If an I/O error has occurred.971*/972public int read() throws IOException {973return bin.read();974}975976/**977* Reads into an array of bytes. This method will block until some input978* is available. Consider using java.io.DataInputStream.readFully to read979* exactly 'length' bytes.980*981* @param buf the buffer into which the data is read982* @param off the start offset of the data983* @param len the maximum number of bytes read984* @return the actual number of bytes read, -1 is returned when the end of985* the stream is reached.986* @throws IOException If an I/O error has occurred.987* @see java.io.DataInputStream#readFully(byte[],int,int)988*/989public int read(byte[] buf, int off, int len) throws IOException {990if (buf == null) {991throw new NullPointerException();992}993int endoff = off + len;994if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {995throw new IndexOutOfBoundsException();996}997return bin.read(buf, off, len, false);998}9991000/**1001* Returns the number of bytes that can be read without blocking.1002*1003* @return the number of available bytes.1004* @throws IOException if there are I/O errors while reading from the1005* underlying <code>InputStream</code>1006*/1007public int available() throws IOException {1008return bin.available();1009}10101011/**1012* Closes the input stream. Must be called to release any resources1013* associated with the stream.1014*1015* @throws IOException If an I/O error has occurred.1016*/1017public void close() throws IOException {1018/*1019* Even if stream already closed, propagate redundant close to1020* underlying stream to stay consistent with previous implementations.1021*/1022closed = true;1023if (depth == 0) {1024clear();1025}1026bin.close();1027}10281029/**1030* Reads in a boolean.1031*1032* @return the boolean read.1033* @throws EOFException If end of file is reached.1034* @throws IOException If other I/O error has occurred.1035*/1036public boolean readBoolean() throws IOException {1037return bin.readBoolean();1038}10391040/**1041* Reads an 8 bit byte.1042*1043* @return the 8 bit byte read.1044* @throws EOFException If end of file is reached.1045* @throws IOException If other I/O error has occurred.1046*/1047public byte readByte() throws IOException {1048return bin.readByte();1049}10501051/**1052* Reads an unsigned 8 bit byte.1053*1054* @return the 8 bit byte read.1055* @throws EOFException If end of file is reached.1056* @throws IOException If other I/O error has occurred.1057*/1058public int readUnsignedByte() throws IOException {1059return bin.readUnsignedByte();1060}10611062/**1063* Reads a 16 bit char.1064*1065* @return the 16 bit char read.1066* @throws EOFException If end of file is reached.1067* @throws IOException If other I/O error has occurred.1068*/1069public char readChar() throws IOException {1070return bin.readChar();1071}10721073/**1074* Reads a 16 bit short.1075*1076* @return the 16 bit short read.1077* @throws EOFException If end of file is reached.1078* @throws IOException If other I/O error has occurred.1079*/1080public short readShort() throws IOException {1081return bin.readShort();1082}10831084/**1085* Reads an unsigned 16 bit short.1086*1087* @return the 16 bit short read.1088* @throws EOFException If end of file is reached.1089* @throws IOException If other I/O error has occurred.1090*/1091public int readUnsignedShort() throws IOException {1092return bin.readUnsignedShort();1093}10941095/**1096* Reads a 32 bit int.1097*1098* @return the 32 bit integer read.1099* @throws EOFException If end of file is reached.1100* @throws IOException If other I/O error has occurred.1101*/1102public int readInt() throws IOException {1103return bin.readInt();1104}11051106/**1107* Reads a 64 bit long.1108*1109* @return the read 64 bit long.1110* @throws EOFException If end of file is reached.1111* @throws IOException If other I/O error has occurred.1112*/1113public long readLong() throws IOException {1114return bin.readLong();1115}11161117/**1118* Reads a 32 bit float.1119*1120* @return the 32 bit float read.1121* @throws EOFException If end of file is reached.1122* @throws IOException If other I/O error has occurred.1123*/1124public float readFloat() throws IOException {1125return bin.readFloat();1126}11271128/**1129* Reads a 64 bit double.1130*1131* @return the 64 bit double read.1132* @throws EOFException If end of file is reached.1133* @throws IOException If other I/O error has occurred.1134*/1135public double readDouble() throws IOException {1136return bin.readDouble();1137}11381139/**1140* Reads bytes, blocking until all bytes are read.1141*1142* @param buf the buffer into which the data is read1143* @throws EOFException If end of file is reached.1144* @throws IOException If other I/O error has occurred.1145*/1146public void readFully(byte[] buf) throws IOException {1147bin.readFully(buf, 0, buf.length, false);1148}11491150/**1151* Reads bytes, blocking until all bytes are read.1152*1153* @param buf the buffer into which the data is read1154* @param off the start offset of the data1155* @param len the maximum number of bytes to read1156* @throws EOFException If end of file is reached.1157* @throws IOException If other I/O error has occurred.1158*/1159public void readFully(byte[] buf, int off, int len) throws IOException {1160int endoff = off + len;1161if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {1162throw new IndexOutOfBoundsException();1163}1164bin.readFully(buf, off, len, false);1165}11661167/**1168* Skips bytes.1169*1170* @param len the number of bytes to be skipped1171* @return the actual number of bytes skipped.1172* @throws IOException If an I/O error has occurred.1173*/1174public int skipBytes(int len) throws IOException {1175return bin.skipBytes(len);1176}11771178/**1179* Reads in a line that has been terminated by a \n, \r, \r\n or EOF.1180*1181* @return a String copy of the line.1182* @throws IOException if there are I/O errors while reading from the1183* underlying <code>InputStream</code>1184* @deprecated This method does not properly convert bytes to characters.1185* see DataInputStream for the details and alternatives.1186*/1187@Deprecated1188public String readLine() throws IOException {1189return bin.readLine();1190}11911192/**1193* Reads a String in1194* <a href="DataInput.html#modified-utf-8">modified UTF-8</a>1195* format.1196*1197* @return the String.1198* @throws IOException if there are I/O errors while reading from the1199* underlying <code>InputStream</code>1200* @throws UTFDataFormatException if read bytes do not represent a valid1201* modified UTF-8 encoding of a string1202*/1203public String readUTF() throws IOException {1204return bin.readUTF();1205}12061207/**1208* Returns the serialization filter for this stream.1209* The serialization filter is the most recent filter set in1210* {@link #setInternalObjectInputFilter setInternalObjectInputFilter} or1211* the initial process-wide filter from1212* {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}.1213*1214* @return the serialization filter for the stream; may be null1215*/1216private final ObjectInputFilter getInternalObjectInputFilter() {1217return serialFilter;1218}12191220/**1221* Set the serialization filter for the stream.1222* The filter's {@link ObjectInputFilter#checkInput checkInput} method is called1223* for each class and reference in the stream.1224* The filter can check any or all of the class, the array length, the number1225* of references, the depth of the graph, and the size of the input stream.1226* <p>1227* If the filter returns {@link ObjectInputFilter.Status#REJECTED Status.REJECTED},1228* {@code null} or throws a {@link RuntimeException},1229* the active {@code readObject} or {@code readUnshared}1230* throws {@link InvalidClassException}, otherwise deserialization1231* continues uninterrupted.1232* <p>1233* The serialization filter is initialized to the value of1234* {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}1235* when the {@code ObjectInputStream} is constructed and can be set1236* to a custom filter only once.1237*1238* @implSpec1239* The filter, when not {@code null}, is invoked during {@link #readObject readObject}1240* and {@link #readUnshared readUnshared} for each object1241* (regular or class) in the stream including the following:1242* <ul>1243* <li>each object reference previously deserialized from the stream1244* (class is {@code null}, arrayLength is -1),1245* <li>each regular class (class is not {@code null}, arrayLength is -1),1246* <li>each interface of a dynamic proxy and the dynamic proxy class itself1247* (class is not {@code null}, arrayLength is -1),1248* <li>each array is filtered using the array type and length of the array1249* (class is the array type, arrayLength is the requested length),1250* <li>each object replaced by its class' {@code readResolve} method1251* is filtered using the replacement object's class, if not {@code null},1252* and if it is an array, the arrayLength, otherwise -1,1253* <li>and each object replaced by {@link #resolveObject resolveObject}1254* is filtered using the replacement object's class, if not {@code null},1255* and if it is an array, the arrayLength, otherwise -1.1256* </ul>1257*1258* When the {@link ObjectInputFilter#checkInput checkInput} method is invoked1259* it is given access to the current class, the array length,1260* the current number of references already read from the stream,1261* the depth of nested calls to {@link #readObject readObject} or1262* {@link #readUnshared readUnshared},1263* and the implementation dependent number of bytes consumed from the input stream.1264* <p>1265* Each call to {@link #readObject readObject} or1266* {@link #readUnshared readUnshared} increases the depth by 11267* before reading an object and decreases by 1 before returning1268* normally or exceptionally.1269* The depth starts at {@code 1} and increases for each nested object and1270* decrements when each nested call returns.1271* The count of references in the stream starts at {@code 1} and1272* is increased before reading an object.1273*1274* @param filter the filter, may be null1275* @throws SecurityException if there is security manager and the1276* {@code SerializablePermission("serialFilter")} is not granted1277* @throws IllegalStateException if the {@linkplain #getInternalObjectInputFilter() current filter}1278* is not {@code null} and is not the process-wide filter1279*/1280private final void setInternalObjectInputFilter(ObjectInputFilter filter) {1281SecurityManager sm = System.getSecurityManager();1282if (sm != null) {1283sm.checkPermission(new SerializablePermission("serialFilter"));1284}1285// Allow replacement of the process-wide filter if not already set1286if (serialFilter != null &&1287serialFilter != ObjectInputFilter.Config.getSerialFilter()) {1288throw new IllegalStateException("filter can not be set more than once");1289}1290if (totalObjectRefs > 0 && !Caches.SET_FILTER_AFTER_READ) {1291throw new IllegalStateException(1292"filter can not be set after an object has been read");1293}1294this.serialFilter = filter;1295}12961297/**1298* Invoke the serialization filter if non-null.1299* If the filter rejects or an exception is thrown, throws InvalidClassException.1300*1301* @param clazz the class; may be null1302* @param arrayLength the array length requested; use {@code -1} if not creating an array1303* @throws InvalidClassException if it rejected by the filter or1304* a {@link RuntimeException} is thrown1305*/1306private void filterCheck(Class<?> clazz, int arrayLength)1307throws InvalidClassException {1308if (serialFilter != null) {1309RuntimeException ex = null;1310ObjectInputFilter.Status status;1311// Info about the stream is not available if overridden by subclass, return 01312long bytesRead = (bin == null) ? 0 : bin.getBytesRead();1313try {1314status = serialFilter.checkInput(new FilterValues(clazz, arrayLength,1315totalObjectRefs, depth, bytesRead));1316} catch (RuntimeException e) {1317// Preventive interception of an exception to log1318status = ObjectInputFilter.Status.REJECTED;1319ex = e;1320}1321if (status == null ||1322status == ObjectInputFilter.Status.REJECTED) {1323// Debug logging of filter checks that fail1324if (Logging.infoLogger != null) {1325Logging.infoLogger.info(1326"ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",1327status, clazz, arrayLength, totalObjectRefs, depth, bytesRead,1328Objects.toString(ex, "n/a"));1329}1330InvalidClassException ice = new InvalidClassException("filter status: " + status);1331ice.initCause(ex);1332throw ice;1333} else {1334// Trace logging for those that succeed1335if (Logging.traceLogger != null) {1336Logging.traceLogger.finer(1337"ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",1338status, clazz, arrayLength, totalObjectRefs, depth, bytesRead,1339Objects.toString(ex, "n/a"));1340}1341}1342}1343}13441345/**1346* Checks the given array type and length to ensure that creation of such1347* an array is permitted by this ObjectInputStream. The arrayType argument1348* must represent an actual array type.1349*1350* This private method is called via SharedSecrets.1351*1352* @param arrayType the array type1353* @param arrayLength the array length1354* @throws NullPointerException if arrayType is null1355* @throws IllegalArgumentException if arrayType isn't actually an array type1356* @throws NegativeArraySizeException if arrayLength is negative1357* @throws InvalidClassException if the filter rejects creation1358*/1359private void checkArray(Class<?> arrayType, int arrayLength) throws InvalidClassException {1360Objects.requireNonNull(arrayType);1361if (! arrayType.isArray()) {1362throw new IllegalArgumentException("not an array type");1363}13641365if (arrayLength < 0) {1366throw new NegativeArraySizeException();1367}13681369filterCheck(arrayType, arrayLength);1370}13711372/**1373* Provide access to the persistent fields read from the input stream.1374*/1375public static abstract class GetField {13761377/**1378* Get the ObjectStreamClass that describes the fields in the stream.1379*1380* @return the descriptor class that describes the serializable fields1381*/1382public abstract ObjectStreamClass getObjectStreamClass();13831384/**1385* Return true if the named field is defaulted and has no value in this1386* stream.1387*1388* @param name the name of the field1389* @return true, if and only if the named field is defaulted1390* @throws IOException if there are I/O errors while reading from1391* the underlying <code>InputStream</code>1392* @throws IllegalArgumentException if <code>name</code> does not1393* correspond to a serializable field1394*/1395public abstract boolean defaulted(String name) throws IOException;13961397/**1398* Get the value of the named boolean field from the persistent field.1399*1400* @param name the name of the field1401* @param val the default value to use if <code>name</code> does not1402* have a value1403* @return the value of the named <code>boolean</code> field1404* @throws IOException if there are I/O errors while reading from the1405* underlying <code>InputStream</code>1406* @throws IllegalArgumentException if type of <code>name</code> is1407* not serializable or if the field type is incorrect1408*/1409public abstract boolean get(String name, boolean val)1410throws IOException;14111412/**1413* Get the value of the named byte field from the persistent field.1414*1415* @param name the name of the field1416* @param val the default value to use if <code>name</code> does not1417* have a value1418* @return the value of the named <code>byte</code> field1419* @throws IOException if there are I/O errors while reading from the1420* underlying <code>InputStream</code>1421* @throws IllegalArgumentException if type of <code>name</code> is1422* not serializable or if the field type is incorrect1423*/1424public abstract byte get(String name, byte val) throws IOException;14251426/**1427* Get the value of the named char field from the persistent field.1428*1429* @param name the name of the field1430* @param val the default value to use if <code>name</code> does not1431* have a value1432* @return the value of the named <code>char</code> field1433* @throws IOException if there are I/O errors while reading from the1434* underlying <code>InputStream</code>1435* @throws IllegalArgumentException if type of <code>name</code> is1436* not serializable or if the field type is incorrect1437*/1438public abstract char get(String name, char val) throws IOException;14391440/**1441* Get the value of the named short field from the persistent field.1442*1443* @param name the name of the field1444* @param val the default value to use if <code>name</code> does not1445* have a value1446* @return the value of the named <code>short</code> field1447* @throws IOException if there are I/O errors while reading from the1448* underlying <code>InputStream</code>1449* @throws IllegalArgumentException if type of <code>name</code> is1450* not serializable or if the field type is incorrect1451*/1452public abstract short get(String name, short val) throws IOException;14531454/**1455* Get the value of the named int field from the persistent field.1456*1457* @param name the name of the field1458* @param val the default value to use if <code>name</code> does not1459* have a value1460* @return the value of the named <code>int</code> field1461* @throws IOException if there are I/O errors while reading from the1462* underlying <code>InputStream</code>1463* @throws IllegalArgumentException if type of <code>name</code> is1464* not serializable or if the field type is incorrect1465*/1466public abstract int get(String name, int val) throws IOException;14671468/**1469* Get the value of the named long field from the persistent field.1470*1471* @param name the name of the field1472* @param val the default value to use if <code>name</code> does not1473* have a value1474* @return the value of the named <code>long</code> field1475* @throws IOException if there are I/O errors while reading from the1476* underlying <code>InputStream</code>1477* @throws IllegalArgumentException if type of <code>name</code> is1478* not serializable or if the field type is incorrect1479*/1480public abstract long get(String name, long val) throws IOException;14811482/**1483* Get the value of the named float field from the persistent field.1484*1485* @param name the name of the field1486* @param val the default value to use if <code>name</code> does not1487* have a value1488* @return the value of the named <code>float</code> field1489* @throws IOException if there are I/O errors while reading from the1490* underlying <code>InputStream</code>1491* @throws IllegalArgumentException if type of <code>name</code> is1492* not serializable or if the field type is incorrect1493*/1494public abstract float get(String name, float val) throws IOException;14951496/**1497* Get the value of the named double field from the persistent field.1498*1499* @param name the name of the field1500* @param val the default value to use if <code>name</code> does not1501* have a value1502* @return the value of the named <code>double</code> field1503* @throws IOException if there are I/O errors while reading from the1504* underlying <code>InputStream</code>1505* @throws IllegalArgumentException if type of <code>name</code> is1506* not serializable or if the field type is incorrect1507*/1508public abstract double get(String name, double val) throws IOException;15091510/**1511* Get the value of the named Object field from the persistent field.1512*1513* @param name the name of the field1514* @param val the default value to use if <code>name</code> does not1515* have a value1516* @return the value of the named <code>Object</code> field1517* @throws IOException if there are I/O errors while reading from the1518* underlying <code>InputStream</code>1519* @throws IllegalArgumentException if type of <code>name</code> is1520* not serializable or if the field type is incorrect1521*/1522public abstract Object get(String name, Object val) throws IOException;1523}15241525/**1526* Verifies that this (possibly subclass) instance can be constructed1527* without violating security constraints: the subclass must not override1528* security-sensitive non-final methods, or else the1529* "enableSubclassImplementation" SerializablePermission is checked.1530*/1531private void verifySubclass() {1532Class<?> cl = getClass();1533if (cl == ObjectInputStream.class) {1534return;1535}1536SecurityManager sm = System.getSecurityManager();1537if (sm == null) {1538return;1539}1540processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);1541WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);1542Boolean result = Caches.subclassAudits.get(key);1543if (result == null) {1544result = Boolean.valueOf(auditSubclass(cl));1545Caches.subclassAudits.putIfAbsent(key, result);1546}1547if (result.booleanValue()) {1548return;1549}1550sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);1551}15521553/**1554* Performs reflective checks on given subclass to verify that it doesn't1555* override security-sensitive non-final methods. Returns true if subclass1556* is "safe", false otherwise.1557*/1558private static boolean auditSubclass(final Class<?> subcl) {1559Boolean result = AccessController.doPrivileged(1560new PrivilegedAction<Boolean>() {1561public Boolean run() {1562for (Class<?> cl = subcl;1563cl != ObjectInputStream.class;1564cl = cl.getSuperclass())1565{1566try {1567cl.getDeclaredMethod(1568"readUnshared", (Class[]) null);1569return Boolean.FALSE;1570} catch (NoSuchMethodException ex) {1571}1572try {1573cl.getDeclaredMethod("readFields", (Class[]) null);1574return Boolean.FALSE;1575} catch (NoSuchMethodException ex) {1576}1577}1578return Boolean.TRUE;1579}1580}1581);1582return result.booleanValue();1583}15841585/**1586* Clears internal data structures.1587*/1588private void clear() {1589handles.clear();1590vlist.clear();1591}15921593/**1594* Underlying readObject implementation.1595* @param type a type expected to be deserialized; non-null1596* @param unshared true if the object can not be a reference to a shared object, otherwise false1597*/1598private Object readObject0(Class<?> type, boolean unshared) throws IOException {1599boolean oldMode = bin.getBlockDataMode();1600if (oldMode) {1601int remain = bin.currentBlockRemaining();1602if (remain > 0) {1603throw new OptionalDataException(remain);1604} else if (defaultDataEnd) {1605/*1606* Fix for 4360508: stream is currently at the end of a field1607* value block written via default serialization; since there1608* is no terminating TC_ENDBLOCKDATA tag, simulate1609* end-of-custom-data behavior explicitly.1610*/1611throw new OptionalDataException(true);1612}1613bin.setBlockDataMode(false);1614}16151616byte tc;1617while ((tc = bin.peekByte()) == TC_RESET) {1618bin.readByte();1619handleReset();1620}16211622depth++;1623totalObjectRefs++;1624try {1625switch (tc) {1626case TC_NULL:1627return readNull();16281629case TC_REFERENCE:1630// check the type of the existing object1631return type.cast(readHandle(unshared));16321633case TC_CLASS:1634if (type == String.class) {1635throw new ClassCastException("Cannot cast a class to java.lang.String");1636}1637return readClass(unshared);16381639case TC_CLASSDESC:1640case TC_PROXYCLASSDESC:1641if (type == String.class) {1642throw new ClassCastException("Cannot cast a class to java.lang.String");1643}1644return readClassDesc(unshared);16451646case TC_STRING:1647case TC_LONGSTRING:1648return checkResolve(readString(unshared));16491650case TC_ARRAY:1651if (type == String.class) {1652throw new ClassCastException("Cannot cast an array to java.lang.String");1653}1654return checkResolve(readArray(unshared));16551656case TC_ENUM:1657if (type == String.class) {1658throw new ClassCastException("Cannot cast an enum to java.lang.String");1659}1660return checkResolve(readEnum(unshared));16611662case TC_OBJECT:1663if (type == String.class) {1664throw new ClassCastException("Cannot cast an object to java.lang.String");1665}1666return checkResolve(readOrdinaryObject(unshared));16671668case TC_EXCEPTION:1669if (type == String.class) {1670throw new ClassCastException("Cannot cast an exception to java.lang.String");1671}1672IOException ex = readFatalException();1673throw new WriteAbortedException("writing aborted", ex);16741675case TC_BLOCKDATA:1676case TC_BLOCKDATALONG:1677if (oldMode) {1678bin.setBlockDataMode(true);1679bin.peek(); // force header read1680throw new OptionalDataException(1681bin.currentBlockRemaining());1682} else {1683throw new StreamCorruptedException(1684"unexpected block data");1685}16861687case TC_ENDBLOCKDATA:1688if (oldMode) {1689throw new OptionalDataException(true);1690} else {1691throw new StreamCorruptedException(1692"unexpected end of block data");1693}16941695default:1696throw new StreamCorruptedException(1697String.format("invalid type code: %02X", tc));1698}1699} finally {1700depth--;1701bin.setBlockDataMode(oldMode);1702}1703}17041705/**1706* If resolveObject has been enabled and given object does not have an1707* exception associated with it, calls resolveObject to determine1708* replacement for object, and updates handle table accordingly. Returns1709* replacement object, or echoes provided object if no replacement1710* occurred. Expects that passHandle is set to given object's handle prior1711* to calling this method.1712*/1713private Object checkResolve(Object obj) throws IOException {1714if (!enableResolve || handles.lookupException(passHandle) != null) {1715return obj;1716}1717Object rep = resolveObject(obj);1718if (rep != obj) {1719// The type of the original object has been filtered but resolveObject1720// may have replaced it; filter the replacement's type1721if (rep != null) {1722if (rep.getClass().isArray()) {1723filterCheck(rep.getClass(), Array.getLength(rep));1724} else {1725filterCheck(rep.getClass(), -1);1726}1727}1728handles.setObject(passHandle, rep);1729}1730return rep;1731}17321733/**1734* Reads string without allowing it to be replaced in stream. Called from1735* within ObjectStreamClass.read().1736*/1737String readTypeString() throws IOException {1738int oldHandle = passHandle;1739try {1740byte tc = bin.peekByte();1741switch (tc) {1742case TC_NULL:1743return (String) readNull();17441745case TC_REFERENCE:1746return (String) readHandle(false);17471748case TC_STRING:1749case TC_LONGSTRING:1750return readString(false);17511752default:1753throw new StreamCorruptedException(1754String.format("invalid type code: %02X", tc));1755}1756} finally {1757passHandle = oldHandle;1758}1759}17601761/**1762* Reads in null code, sets passHandle to NULL_HANDLE and returns null.1763*/1764private Object readNull() throws IOException {1765if (bin.readByte() != TC_NULL) {1766throw new InternalError();1767}1768passHandle = NULL_HANDLE;1769return null;1770}17711772/**1773* Reads in object handle, sets passHandle to the read handle, and returns1774* object associated with the handle.1775*/1776private Object readHandle(boolean unshared) throws IOException {1777if (bin.readByte() != TC_REFERENCE) {1778throw new InternalError();1779}1780passHandle = bin.readInt() - baseWireHandle;1781if (passHandle < 0 || passHandle >= handles.size()) {1782throw new StreamCorruptedException(1783String.format("invalid handle value: %08X", passHandle +1784baseWireHandle));1785}1786if (unshared) {1787// REMIND: what type of exception to throw here?1788throw new InvalidObjectException(1789"cannot read back reference as unshared");1790}17911792Object obj = handles.lookupObject(passHandle);1793if (obj == unsharedMarker) {1794// REMIND: what type of exception to throw here?1795throw new InvalidObjectException(1796"cannot read back reference to unshared object");1797}1798filterCheck(null, -1); // just a check for number of references, depth, no class1799return obj;1800}18011802/**1803* Reads in and returns class object. Sets passHandle to class object's1804* assigned handle. Returns null if class is unresolvable (in which case a1805* ClassNotFoundException will be associated with the class' handle in the1806* handle table).1807*/1808private Class<?> readClass(boolean unshared) throws IOException {1809if (bin.readByte() != TC_CLASS) {1810throw new InternalError();1811}1812ObjectStreamClass desc = readClassDesc(false);1813Class<?> cl = desc.forClass();1814passHandle = handles.assign(unshared ? unsharedMarker : cl);18151816ClassNotFoundException resolveEx = desc.getResolveException();1817if (resolveEx != null) {1818handles.markException(passHandle, resolveEx);1819}18201821handles.finish(passHandle);1822return cl;1823}18241825/**1826* Reads in and returns (possibly null) class descriptor. Sets passHandle1827* to class descriptor's assigned handle. If class descriptor cannot be1828* resolved to a class in the local VM, a ClassNotFoundException is1829* associated with the class descriptor's handle.1830*/1831private ObjectStreamClass readClassDesc(boolean unshared)1832throws IOException1833{1834byte tc = bin.peekByte();1835ObjectStreamClass descriptor;1836switch (tc) {1837case TC_NULL:1838descriptor = (ObjectStreamClass) readNull();1839break;1840case TC_REFERENCE:1841descriptor = (ObjectStreamClass) readHandle(unshared);1842// Should only reference initialized class descriptors1843descriptor.checkInitialized();1844break;1845case TC_PROXYCLASSDESC:1846descriptor = readProxyDesc(unshared);1847break;1848case TC_CLASSDESC:1849descriptor = readNonProxyDesc(unshared);1850break;1851default:1852throw new StreamCorruptedException(1853String.format("invalid type code: %02X", tc));1854}1855if (descriptor != null) {1856validateDescriptor(descriptor);1857}1858return descriptor;1859}18601861private boolean isCustomSubclass() {1862// Return true if this class is a custom subclass of ObjectInputStream1863return getClass().getClassLoader()1864!= ObjectInputStream.class.getClassLoader();1865}18661867/**1868* Reads in and returns class descriptor for a dynamic proxy class. Sets1869* passHandle to proxy class descriptor's assigned handle. If proxy class1870* descriptor cannot be resolved to a class in the local VM, a1871* ClassNotFoundException is associated with the descriptor's handle.1872*/1873private ObjectStreamClass readProxyDesc(boolean unshared)1874throws IOException1875{1876if (bin.readByte() != TC_PROXYCLASSDESC) {1877throw new InternalError();1878}18791880ObjectStreamClass desc = new ObjectStreamClass();1881int descHandle = handles.assign(unshared ? unsharedMarker : desc);1882passHandle = NULL_HANDLE;18831884int numIfaces = bin.readInt();1885if (numIfaces > 65535) {1886// Report specification limit exceeded1887throw new InvalidObjectException("interface limit exceeded: " +1888numIfaces +1889", limit: " + Caches.PROXY_INTERFACE_LIMIT);1890}1891String[] ifaces = new String[numIfaces];1892for (int i = 0; i < numIfaces; i++) {1893ifaces[i] = bin.readUTF();1894}18951896// Recheck against implementation limit and throw with interface names1897if (numIfaces > Caches.PROXY_INTERFACE_LIMIT) {1898throw new InvalidObjectException("interface limit exceeded: " +1899numIfaces +1900", limit: " + Caches.PROXY_INTERFACE_LIMIT +1901"; " + Arrays.toString(ifaces));1902}1903Class<?> cl = null;1904ClassNotFoundException resolveEx = null;1905bin.setBlockDataMode(true);1906try {1907if ((cl = resolveProxyClass(ifaces)) == null) {1908resolveEx = new ClassNotFoundException("null class");1909} else if (!Proxy.isProxyClass(cl)) {1910throw new InvalidClassException("Not a proxy");1911} else {1912// ReflectUtil.checkProxyPackageAccess makes a test1913// equivalent to isCustomSubclass so there's no need1914// to condition this call to isCustomSubclass == true here.1915ReflectUtil.checkProxyPackageAccess(1916getClass().getClassLoader(),1917cl.getInterfaces());1918// Filter the interfaces1919for (Class<?> clazz : cl.getInterfaces()) {1920filterCheck(clazz, -1);1921}1922}1923} catch (ClassNotFoundException ex) {1924resolveEx = ex;1925} catch (OutOfMemoryError memerr) {1926IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " +1927Arrays.toString(ifaces));1928ex.initCause(memerr);1929throw ex;1930}19311932// Call filterCheck on the class before reading anything else1933filterCheck(cl, -1);19341935skipCustomData();19361937try {1938totalObjectRefs++;1939depth++;1940desc.initProxy(cl, resolveEx, readClassDesc(false));1941} catch (OutOfMemoryError memerr) {1942IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " +1943Arrays.toString(ifaces));1944ex.initCause(memerr);1945throw ex;1946} finally {1947depth--;1948}19491950handles.finish(descHandle);1951passHandle = descHandle;1952return desc;1953}19541955/**1956* Reads in and returns class descriptor for a class that is not a dynamic1957* proxy class. Sets passHandle to class descriptor's assigned handle. If1958* class descriptor cannot be resolved to a class in the local VM, a1959* ClassNotFoundException is associated with the descriptor's handle.1960*/1961private ObjectStreamClass readNonProxyDesc(boolean unshared)1962throws IOException1963{1964if (bin.readByte() != TC_CLASSDESC) {1965throw new InternalError();1966}19671968ObjectStreamClass desc = new ObjectStreamClass();1969int descHandle = handles.assign(unshared ? unsharedMarker : desc);1970passHandle = NULL_HANDLE;19711972ObjectStreamClass readDesc = null;1973try {1974readDesc = readClassDescriptor();1975} catch (ClassNotFoundException ex) {1976throw (IOException) new InvalidClassException(1977"failed to read class descriptor").initCause(ex);1978}19791980Class<?> cl = null;1981ClassNotFoundException resolveEx = null;1982bin.setBlockDataMode(true);1983final boolean checksRequired = isCustomSubclass();1984try {1985if ((cl = resolveClass(readDesc)) == null) {1986resolveEx = new ClassNotFoundException("null class");1987} else if (checksRequired) {1988ReflectUtil.checkPackageAccess(cl);1989}1990} catch (ClassNotFoundException ex) {1991resolveEx = ex;1992}19931994// Call filterCheck on the class before reading anything else1995filterCheck(cl, -1);19961997skipCustomData();19981999try {2000totalObjectRefs++;2001depth++;2002desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));2003} finally {2004depth--;2005}20062007handles.finish(descHandle);2008passHandle = descHandle;20092010return desc;2011}20122013/**2014* Reads in and returns new string. Sets passHandle to new string's2015* assigned handle.2016*/2017private String readString(boolean unshared) throws IOException {2018String str;2019byte tc = bin.readByte();2020switch (tc) {2021case TC_STRING:2022str = bin.readUTF();2023break;20242025case TC_LONGSTRING:2026str = bin.readLongUTF();2027break;20282029default:2030throw new StreamCorruptedException(2031String.format("invalid type code: %02X", tc));2032}2033passHandle = handles.assign(unshared ? unsharedMarker : str);2034handles.finish(passHandle);2035return str;2036}20372038/**2039* Reads in and returns array object, or null if array class is2040* unresolvable. Sets passHandle to array's assigned handle.2041*/2042private Object readArray(boolean unshared) throws IOException {2043if (bin.readByte() != TC_ARRAY) {2044throw new InternalError();2045}20462047ObjectStreamClass desc = readClassDesc(false);2048int len = bin.readInt();20492050filterCheck(desc.forClass(), len);20512052Object array = null;2053Class<?> cl, ccl = null;2054if ((cl = desc.forClass()) != null) {2055ccl = cl.getComponentType();2056array = Array.newInstance(ccl, len);2057}20582059int arrayHandle = handles.assign(unshared ? unsharedMarker : array);2060ClassNotFoundException resolveEx = desc.getResolveException();2061if (resolveEx != null) {2062handles.markException(arrayHandle, resolveEx);2063}20642065if (ccl == null) {2066for (int i = 0; i < len; i++) {2067readObject0(Object.class, false);2068}2069} else if (ccl.isPrimitive()) {2070if (ccl == Integer.TYPE) {2071bin.readInts((int[]) array, 0, len);2072} else if (ccl == Byte.TYPE) {2073bin.readFully((byte[]) array, 0, len, true);2074} else if (ccl == Long.TYPE) {2075bin.readLongs((long[]) array, 0, len);2076} else if (ccl == Float.TYPE) {2077bin.readFloats((float[]) array, 0, len);2078} else if (ccl == Double.TYPE) {2079bin.readDoubles((double[]) array, 0, len);2080} else if (ccl == Short.TYPE) {2081bin.readShorts((short[]) array, 0, len);2082} else if (ccl == Character.TYPE) {2083bin.readChars((char[]) array, 0, len);2084} else if (ccl == Boolean.TYPE) {2085bin.readBooleans((boolean[]) array, 0, len);2086} else {2087throw new InternalError();2088}2089} else {2090Object[] oa = (Object[]) array;2091for (int i = 0; i < len; i++) {2092oa[i] = readObject0(Object.class, false);2093handles.markDependency(arrayHandle, passHandle);2094}2095}20962097handles.finish(arrayHandle);2098passHandle = arrayHandle;2099return array;2100}21012102/**2103* Reads in and returns enum constant, or null if enum type is2104* unresolvable. Sets passHandle to enum constant's assigned handle.2105*/2106private Enum<?> readEnum(boolean unshared) throws IOException {2107if (bin.readByte() != TC_ENUM) {2108throw new InternalError();2109}21102111ObjectStreamClass desc = readClassDesc(false);2112if (!desc.isEnum()) {2113throw new InvalidClassException("non-enum class: " + desc);2114}21152116int enumHandle = handles.assign(unshared ? unsharedMarker : null);2117ClassNotFoundException resolveEx = desc.getResolveException();2118if (resolveEx != null) {2119handles.markException(enumHandle, resolveEx);2120}21212122String name = readString(false);2123Enum<?> result = null;2124Class<?> cl = desc.forClass();2125if (cl != null) {2126try {2127@SuppressWarnings("unchecked")2128Enum<?> en = Enum.valueOf((Class)cl, name);2129result = en;2130} catch (IllegalArgumentException ex) {2131throw (IOException) new InvalidObjectException(2132"enum constant " + name + " does not exist in " +2133cl).initCause(ex);2134}2135if (!unshared) {2136handles.setObject(enumHandle, result);2137}2138}21392140handles.finish(enumHandle);2141passHandle = enumHandle;2142return result;2143}21442145/**2146* Reads and returns "ordinary" (i.e., not a String, Class,2147* ObjectStreamClass, array, or enum constant) object, or null if object's2148* class is unresolvable (in which case a ClassNotFoundException will be2149* associated with object's handle). Sets passHandle to object's assigned2150* handle.2151*/2152private Object readOrdinaryObject(boolean unshared)2153throws IOException2154{2155if (bin.readByte() != TC_OBJECT) {2156throw new InternalError();2157}21582159ObjectStreamClass desc = readClassDesc(false);2160desc.checkDeserialize();21612162Class<?> cl = desc.forClass();2163if (cl == String.class || cl == Class.class2164|| cl == ObjectStreamClass.class) {2165throw new InvalidClassException("invalid class descriptor");2166}21672168Object obj;2169try {2170obj = desc.isInstantiable() ? desc.newInstance() : null;2171} catch (Exception ex) {2172throw (IOException) new InvalidClassException(2173desc.forClass().getName(),2174"unable to create instance").initCause(ex);2175}21762177passHandle = handles.assign(unshared ? unsharedMarker : obj);2178ClassNotFoundException resolveEx = desc.getResolveException();2179if (resolveEx != null) {2180handles.markException(passHandle, resolveEx);2181}21822183if (desc.isExternalizable()) {2184readExternalData((Externalizable) obj, desc);2185} else {2186readSerialData(obj, desc);2187}21882189handles.finish(passHandle);21902191if (obj != null &&2192handles.lookupException(passHandle) == null &&2193desc.hasReadResolveMethod())2194{2195Object rep = desc.invokeReadResolve(obj);2196if (unshared && rep.getClass().isArray()) {2197rep = cloneArray(rep);2198}2199if (rep != obj) {2200// Filter the replacement object2201if (rep != null) {2202if (rep.getClass().isArray()) {2203filterCheck(rep.getClass(), Array.getLength(rep));2204} else {2205filterCheck(rep.getClass(), -1);2206}2207}2208handles.setObject(passHandle, obj = rep);2209}2210}22112212return obj;2213}22142215/**2216* If obj is non-null, reads externalizable data by invoking readExternal()2217* method of obj; otherwise, attempts to skip over externalizable data.2218* Expects that passHandle is set to obj's handle before this method is2219* called.2220*/2221private void readExternalData(Externalizable obj, ObjectStreamClass desc)2222throws IOException2223{2224SerialCallbackContext oldContext = curContext;2225if (oldContext != null)2226oldContext.check();2227curContext = null;2228try {2229boolean blocked = desc.hasBlockExternalData();2230if (blocked) {2231bin.setBlockDataMode(true);2232}2233if (obj != null) {2234try {2235obj.readExternal(this);2236} catch (ClassNotFoundException ex) {2237/*2238* In most cases, the handle table has already propagated2239* a CNFException to passHandle at this point; this mark2240* call is included to address cases where the readExternal2241* method has cons'ed and thrown a new CNFException of its2242* own.2243*/2244handles.markException(passHandle, ex);2245}2246}2247if (blocked) {2248skipCustomData();2249}2250} finally {2251if (oldContext != null)2252oldContext.check();2253curContext = oldContext;2254}2255/*2256* At this point, if the externalizable data was not written in2257* block-data form and either the externalizable class doesn't exist2258* locally (i.e., obj == null) or readExternal() just threw a2259* CNFException, then the stream is probably in an inconsistent state,2260* since some (or all) of the externalizable data may not have been2261* consumed. Since there's no "correct" action to take in this case,2262* we mimic the behavior of past serialization implementations and2263* blindly hope that the stream is in sync; if it isn't and additional2264* externalizable data remains in the stream, a subsequent read will2265* most likely throw a StreamCorruptedException.2266*/2267}22682269/**2270* Reads (or attempts to skip, if obj is null or is tagged with a2271* ClassNotFoundException) instance data for each serializable class of2272* object in stream, from superclass to subclass. Expects that passHandle2273* is set to obj's handle before this method is called.2274*/2275private void readSerialData(Object obj, ObjectStreamClass desc)2276throws IOException2277{2278ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();2279for (int i = 0; i < slots.length; i++) {2280ObjectStreamClass slotDesc = slots[i].desc;22812282if (slots[i].hasData) {2283if (obj == null || handles.lookupException(passHandle) != null) {2284defaultReadFields(null, slotDesc); // skip field values2285} else if (slotDesc.hasReadObjectMethod()) {2286ThreadDeath t = null;2287boolean reset = false;2288SerialCallbackContext oldContext = curContext;2289if (oldContext != null)2290oldContext.check();2291try {2292curContext = new SerialCallbackContext(obj, slotDesc);22932294bin.setBlockDataMode(true);2295slotDesc.invokeReadObject(obj, this);2296} catch (ClassNotFoundException ex) {2297/*2298* In most cases, the handle table has already2299* propagated a CNFException to passHandle at this2300* point; this mark call is included to address cases2301* where the custom readObject method has cons'ed and2302* thrown a new CNFException of its own.2303*/2304handles.markException(passHandle, ex);2305} finally {2306do {2307try {2308curContext.setUsed();2309if (oldContext!= null)2310oldContext.check();2311curContext = oldContext;2312reset = true;2313} catch (ThreadDeath x) {2314t = x; // defer until reset is true2315}2316} while (!reset);2317if (t != null)2318throw t;2319}23202321/*2322* defaultDataEnd may have been set indirectly by custom2323* readObject() method when calling defaultReadObject() or2324* readFields(); clear it to restore normal read behavior.2325*/2326defaultDataEnd = false;2327} else {2328defaultReadFields(obj, slotDesc);2329}23302331if (slotDesc.hasWriteObjectData()) {2332skipCustomData();2333} else {2334bin.setBlockDataMode(false);2335}2336} else {2337if (obj != null &&2338slotDesc.hasReadObjectNoDataMethod() &&2339handles.lookupException(passHandle) == null)2340{2341slotDesc.invokeReadObjectNoData(obj);2342}2343}2344}2345}23462347/**2348* Skips over all block data and objects until TC_ENDBLOCKDATA is2349* encountered.2350*/2351private void skipCustomData() throws IOException {2352int oldHandle = passHandle;2353for (;;) {2354if (bin.getBlockDataMode()) {2355bin.skipBlockData();2356bin.setBlockDataMode(false);2357}2358switch (bin.peekByte()) {2359case TC_BLOCKDATA:2360case TC_BLOCKDATALONG:2361bin.setBlockDataMode(true);2362break;23632364case TC_ENDBLOCKDATA:2365bin.readByte();2366passHandle = oldHandle;2367return;23682369default:2370readObject0(Object.class, false);2371break;2372}2373}2374}23752376/**2377* Reads in values of serializable fields declared by given class2378* descriptor. If obj is non-null, sets field values in obj. Expects that2379* passHandle is set to obj's handle before this method is called.2380*/2381private void defaultReadFields(Object obj, ObjectStreamClass desc)2382throws IOException2383{2384Class<?> cl = desc.forClass();2385if (cl != null && obj != null && !cl.isInstance(obj)) {2386throw new ClassCastException();2387}23882389int primDataSize = desc.getPrimDataSize();2390if (primVals == null || primVals.length < primDataSize) {2391primVals = new byte[primDataSize];2392}2393bin.readFully(primVals, 0, primDataSize, false);2394if (obj != null) {2395desc.setPrimFieldValues(obj, primVals);2396}23972398int objHandle = passHandle;2399ObjectStreamField[] fields = desc.getFields(false);2400Object[] objVals = new Object[desc.getNumObjFields()];2401int numPrimFields = fields.length - objVals.length;2402for (int i = 0; i < objVals.length; i++) {2403ObjectStreamField f = fields[numPrimFields + i];2404objVals[i] = readObject0(Object.class, f.isUnshared());2405if (f.getField() != null) {2406handles.markDependency(objHandle, passHandle);2407}2408}2409if (obj != null) {2410desc.setObjFieldValues(obj, objVals);2411}2412passHandle = objHandle;2413}24142415/**2416* Reads in and returns IOException that caused serialization to abort.2417* All stream state is discarded prior to reading in fatal exception. Sets2418* passHandle to fatal exception's handle.2419*/2420private IOException readFatalException() throws IOException {2421if (bin.readByte() != TC_EXCEPTION) {2422throw new InternalError();2423}2424clear();2425return (IOException) readObject0(Object.class, false);2426}24272428/**2429* If recursion depth is 0, clears internal data structures; otherwise,2430* throws a StreamCorruptedException. This method is called when a2431* TC_RESET typecode is encountered.2432*/2433private void handleReset() throws StreamCorruptedException {2434if (depth > 0) {2435throw new StreamCorruptedException(2436"unexpected reset; recursion depth: " + depth);2437}2438clear();2439}24402441/**2442* Converts specified span of bytes into float values.2443*/2444// REMIND: remove once hotspot inlines Float.intBitsToFloat2445private static native void bytesToFloats(byte[] src, int srcpos,2446float[] dst, int dstpos,2447int nfloats);24482449/**2450* Converts specified span of bytes into double values.2451*/2452// REMIND: remove once hotspot inlines Double.longBitsToDouble2453private static native void bytesToDoubles(byte[] src, int srcpos,2454double[] dst, int dstpos,2455int ndoubles);24562457/**2458* Returns first non-privileged class loader on the stack (excluding2459* reflection generated frames) or the extension class loader if only2460* class loaded by the boot class loader and extension class loader are2461* found on the stack. This method is also called via reflection by the2462* following RMI-IIOP class:2463*2464* com.sun.corba.se.internal.util.JDKClassLoader2465*2466* This method should not be removed or its signature changed without2467* corresponding modifications to the above class.2468*/2469private static ClassLoader latestUserDefinedLoader() {2470return sun.misc.VM.latestUserDefinedLoader();2471}24722473/**2474* Default GetField implementation.2475*/2476private class GetFieldImpl extends GetField {24772478/** class descriptor describing serializable fields */2479private final ObjectStreamClass desc;2480/** primitive field values */2481private final byte[] primVals;2482/** object field values */2483private final Object[] objVals;2484/** object field value handles */2485private final int[] objHandles;24862487/**2488* Creates GetFieldImpl object for reading fields defined in given2489* class descriptor.2490*/2491GetFieldImpl(ObjectStreamClass desc) {2492this.desc = desc;2493primVals = new byte[desc.getPrimDataSize()];2494objVals = new Object[desc.getNumObjFields()];2495objHandles = new int[objVals.length];2496}24972498public ObjectStreamClass getObjectStreamClass() {2499return desc;2500}25012502public boolean defaulted(String name) throws IOException {2503return (getFieldOffset(name, null) < 0);2504}25052506public boolean get(String name, boolean val) throws IOException {2507int off = getFieldOffset(name, Boolean.TYPE);2508return (off >= 0) ? Bits.getBoolean(primVals, off) : val;2509}25102511public byte get(String name, byte val) throws IOException {2512int off = getFieldOffset(name, Byte.TYPE);2513return (off >= 0) ? primVals[off] : val;2514}25152516public char get(String name, char val) throws IOException {2517int off = getFieldOffset(name, Character.TYPE);2518return (off >= 0) ? Bits.getChar(primVals, off) : val;2519}25202521public short get(String name, short val) throws IOException {2522int off = getFieldOffset(name, Short.TYPE);2523return (off >= 0) ? Bits.getShort(primVals, off) : val;2524}25252526public int get(String name, int val) throws IOException {2527int off = getFieldOffset(name, Integer.TYPE);2528return (off >= 0) ? Bits.getInt(primVals, off) : val;2529}25302531public float get(String name, float val) throws IOException {2532int off = getFieldOffset(name, Float.TYPE);2533return (off >= 0) ? Bits.getFloat(primVals, off) : val;2534}25352536public long get(String name, long val) throws IOException {2537int off = getFieldOffset(name, Long.TYPE);2538return (off >= 0) ? Bits.getLong(primVals, off) : val;2539}25402541public double get(String name, double val) throws IOException {2542int off = getFieldOffset(name, Double.TYPE);2543return (off >= 0) ? Bits.getDouble(primVals, off) : val;2544}25452546public Object get(String name, Object val) throws IOException {2547int off = getFieldOffset(name, Object.class);2548if (off >= 0) {2549int objHandle = objHandles[off];2550handles.markDependency(passHandle, objHandle);2551return (handles.lookupException(objHandle) == null) ?2552objVals[off] : null;2553} else {2554return val;2555}2556}25572558/**2559* Reads primitive and object field values from stream.2560*/2561void readFields() throws IOException {2562bin.readFully(primVals, 0, primVals.length, false);25632564int oldHandle = passHandle;2565ObjectStreamField[] fields = desc.getFields(false);2566int numPrimFields = fields.length - objVals.length;2567for (int i = 0; i < objVals.length; i++) {2568objVals[i] =2569readObject0(Object.class, fields[numPrimFields + i].isUnshared());2570objHandles[i] = passHandle;2571}2572passHandle = oldHandle;2573}25742575/**2576* Returns offset of field with given name and type. A specified type2577* of null matches all types, Object.class matches all non-primitive2578* types, and any other non-null type matches assignable types only.2579* If no matching field is found in the (incoming) class2580* descriptor but a matching field is present in the associated local2581* class descriptor, returns -1. Throws IllegalArgumentException if2582* neither incoming nor local class descriptor contains a match.2583*/2584private int getFieldOffset(String name, Class<?> type) {2585ObjectStreamField field = desc.getField(name, type);2586if (field != null) {2587return field.getOffset();2588} else if (desc.getLocalDesc().getField(name, type) != null) {2589return -1;2590} else {2591throw new IllegalArgumentException("no such field " + name +2592" with type " + type);2593}2594}2595}25962597/**2598* Prioritized list of callbacks to be performed once object graph has been2599* completely deserialized.2600*/2601private static class ValidationList {26022603private static class Callback {2604final ObjectInputValidation obj;2605final int priority;2606Callback next;2607final AccessControlContext acc;26082609Callback(ObjectInputValidation obj, int priority, Callback next,2610AccessControlContext acc)2611{2612this.obj = obj;2613this.priority = priority;2614this.next = next;2615this.acc = acc;2616}2617}26182619/** linked list of callbacks */2620private Callback list;26212622/**2623* Creates new (empty) ValidationList.2624*/2625ValidationList() {2626}26272628/**2629* Registers callback. Throws InvalidObjectException if callback2630* object is null.2631*/2632void register(ObjectInputValidation obj, int priority)2633throws InvalidObjectException2634{2635if (obj == null) {2636throw new InvalidObjectException("null callback");2637}26382639Callback prev = null, cur = list;2640while (cur != null && priority < cur.priority) {2641prev = cur;2642cur = cur.next;2643}2644AccessControlContext acc = AccessController.getContext();2645if (prev != null) {2646prev.next = new Callback(obj, priority, cur, acc);2647} else {2648list = new Callback(obj, priority, list, acc);2649}2650}26512652/**2653* Invokes all registered callbacks and clears the callback list.2654* Callbacks with higher priorities are called first; those with equal2655* priorities may be called in any order. If any of the callbacks2656* throws an InvalidObjectException, the callback process is terminated2657* and the exception propagated upwards.2658*/2659void doCallbacks() throws InvalidObjectException {2660try {2661while (list != null) {2662AccessController.doPrivileged(2663new PrivilegedExceptionAction<Void>()2664{2665public Void run() throws InvalidObjectException {2666list.obj.validateObject();2667return null;2668}2669}, list.acc);2670list = list.next;2671}2672} catch (PrivilegedActionException ex) {2673list = null;2674throw (InvalidObjectException) ex.getException();2675}2676}26772678/**2679* Resets the callback list to its initial (empty) state.2680*/2681public void clear() {2682list = null;2683}2684}26852686/**2687* Hold a snapshot of values to be passed to an ObjectInputFilter.2688*/2689static class FilterValues implements ObjectInputFilter.FilterInfo {2690final Class<?> clazz;2691final long arrayLength;2692final long totalObjectRefs;2693final long depth;2694final long streamBytes;26952696public FilterValues(Class<?> clazz, long arrayLength, long totalObjectRefs,2697long depth, long streamBytes) {2698this.clazz = clazz;2699this.arrayLength = arrayLength;2700this.totalObjectRefs = totalObjectRefs;2701this.depth = depth;2702this.streamBytes = streamBytes;2703}27042705@Override2706public Class<?> serialClass() {2707return clazz;2708}27092710@Override2711public long arrayLength() {2712return arrayLength;2713}27142715@Override2716public long references() {2717return totalObjectRefs;2718}27192720@Override2721public long depth() {2722return depth;2723}27242725@Override2726public long streamBytes() {2727return streamBytes;2728}2729}27302731/**2732* Input stream supporting single-byte peek operations.2733*/2734private static class PeekInputStream extends InputStream {27352736/** underlying stream */2737private final InputStream in;2738/** peeked byte */2739private int peekb = -1;2740/** total bytes read from the stream */2741private long totalBytesRead = 0;27422743/**2744* Creates new PeekInputStream on top of given underlying stream.2745*/2746PeekInputStream(InputStream in) {2747this.in = in;2748}27492750/**2751* Peeks at next byte value in stream. Similar to read(), except2752* that it does not consume the read value.2753*/2754int peek() throws IOException {2755if (peekb >= 0) {2756return peekb;2757}2758peekb = in.read();2759totalBytesRead += peekb >= 0 ? 1 : 0;2760return peekb;2761}27622763public int read() throws IOException {2764if (peekb >= 0) {2765int v = peekb;2766peekb = -1;2767return v;2768} else {2769int nbytes = in.read();2770totalBytesRead += nbytes >= 0 ? 1 : 0;2771return nbytes;2772}2773}27742775public int read(byte[] b, int off, int len) throws IOException {2776int nbytes;2777if (len == 0) {2778return 0;2779} else if (peekb < 0) {2780nbytes = in.read(b, off, len);2781totalBytesRead += nbytes >= 0 ? nbytes : 0;2782return nbytes;2783} else {2784b[off++] = (byte) peekb;2785len--;2786peekb = -1;2787nbytes = in.read(b, off, len);2788totalBytesRead += nbytes >= 0 ? nbytes : 0;2789return (nbytes >= 0) ? (nbytes + 1) : 1;2790}2791}27922793void readFully(byte[] b, int off, int len) throws IOException {2794int n = 0;2795while (n < len) {2796int count = read(b, off + n, len - n);2797if (count < 0) {2798throw new EOFException();2799}2800n += count;2801}2802}28032804public long skip(long n) throws IOException {2805if (n <= 0) {2806return 0;2807}2808int skipped = 0;2809if (peekb >= 0) {2810peekb = -1;2811skipped++;2812n--;2813}2814n = skipped + in.skip(n);2815totalBytesRead += n;2816return n;2817}28182819public int available() throws IOException {2820return in.available() + ((peekb >= 0) ? 1 : 0);2821}28222823public void close() throws IOException {2824in.close();2825}28262827public long getBytesRead() {2828return totalBytesRead;2829}2830}28312832/**2833* Input stream with two modes: in default mode, inputs data written in the2834* same format as DataOutputStream; in "block data" mode, inputs data2835* bracketed by block data markers (see object serialization specification2836* for details). Buffering depends on block data mode: when in default2837* mode, no data is buffered in advance; when in block data mode, all data2838* for the current data block is read in at once (and buffered).2839*/2840private class BlockDataInputStream2841extends InputStream implements DataInput2842{2843/** maximum data block length */2844private static final int MAX_BLOCK_SIZE = 1024;2845/** maximum data block header length */2846private static final int MAX_HEADER_SIZE = 5;2847/** (tunable) length of char buffer (for reading strings) */2848private static final int CHAR_BUF_SIZE = 256;2849/** readBlockHeader() return value indicating header read may block */2850private static final int HEADER_BLOCKED = -2;28512852/** buffer for reading general/block data */2853private final byte[] buf = new byte[MAX_BLOCK_SIZE];2854/** buffer for reading block data headers */2855private final byte[] hbuf = new byte[MAX_HEADER_SIZE];2856/** char buffer for fast string reads */2857private final char[] cbuf = new char[CHAR_BUF_SIZE];28582859/** block data mode */2860private boolean blkmode = false;28612862// block data state fields; values meaningful only when blkmode true2863/** current offset into buf */2864private int pos = 0;2865/** end offset of valid data in buf, or -1 if no more block data */2866private int end = -1;2867/** number of bytes in current block yet to be read from stream */2868private int unread = 0;28692870/** underlying stream (wrapped in peekable filter stream) */2871private final PeekInputStream in;2872/** loopback stream (for data reads that span data blocks) */2873private final DataInputStream din;28742875/**2876* Creates new BlockDataInputStream on top of given underlying stream.2877* Block data mode is turned off by default.2878*/2879BlockDataInputStream(InputStream in) {2880this.in = new PeekInputStream(in);2881din = new DataInputStream(this);2882}28832884/**2885* Sets block data mode to the given mode (true == on, false == off)2886* and returns the previous mode value. If the new mode is the same as2887* the old mode, no action is taken. Throws IllegalStateException if2888* block data mode is being switched from on to off while unconsumed2889* block data is still present in the stream.2890*/2891boolean setBlockDataMode(boolean newmode) throws IOException {2892if (blkmode == newmode) {2893return blkmode;2894}2895if (newmode) {2896pos = 0;2897end = 0;2898unread = 0;2899} else if (pos < end) {2900throw new IllegalStateException("unread block data");2901}2902blkmode = newmode;2903return !blkmode;2904}29052906/**2907* Returns true if the stream is currently in block data mode, false2908* otherwise.2909*/2910boolean getBlockDataMode() {2911return blkmode;2912}29132914/**2915* If in block data mode, skips to the end of the current group of data2916* blocks (but does not unset block data mode). If not in block data2917* mode, throws an IllegalStateException.2918*/2919void skipBlockData() throws IOException {2920if (!blkmode) {2921throw new IllegalStateException("not in block data mode");2922}2923while (end >= 0) {2924refill();2925}2926}29272928/**2929* Attempts to read in the next block data header (if any). If2930* canBlock is false and a full header cannot be read without possibly2931* blocking, returns HEADER_BLOCKED, else if the next element in the2932* stream is a block data header, returns the block data length2933* specified by the header, else returns -1.2934*/2935private int readBlockHeader(boolean canBlock) throws IOException {2936if (defaultDataEnd) {2937/*2938* Fix for 4360508: stream is currently at the end of a field2939* value block written via default serialization; since there2940* is no terminating TC_ENDBLOCKDATA tag, simulate2941* end-of-custom-data behavior explicitly.2942*/2943return -1;2944}2945try {2946for (;;) {2947int avail = canBlock ? Integer.MAX_VALUE : in.available();2948if (avail == 0) {2949return HEADER_BLOCKED;2950}29512952int tc = in.peek();2953switch (tc) {2954case TC_BLOCKDATA:2955if (avail < 2) {2956return HEADER_BLOCKED;2957}2958in.readFully(hbuf, 0, 2);2959return hbuf[1] & 0xFF;29602961case TC_BLOCKDATALONG:2962if (avail < 5) {2963return HEADER_BLOCKED;2964}2965in.readFully(hbuf, 0, 5);2966int len = Bits.getInt(hbuf, 1);2967if (len < 0) {2968throw new StreamCorruptedException(2969"illegal block data header length: " +2970len);2971}2972return len;29732974/*2975* TC_RESETs may occur in between data blocks.2976* Unfortunately, this case must be parsed at a lower2977* level than other typecodes, since primitive data2978* reads may span data blocks separated by a TC_RESET.2979*/2980case TC_RESET:2981in.read();2982handleReset();2983break;29842985default:2986if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {2987throw new StreamCorruptedException(2988String.format("invalid type code: %02X",2989tc));2990}2991return -1;2992}2993}2994} catch (EOFException ex) {2995throw new StreamCorruptedException(2996"unexpected EOF while reading block data header");2997}2998}29993000/**3001* Refills internal buffer buf with block data. Any data in buf at the3002* time of the call is considered consumed. Sets the pos, end, and3003* unread fields to reflect the new amount of available block data; if3004* the next element in the stream is not a data block, sets pos and3005* unread to 0 and end to -1.3006*/3007private void refill() throws IOException {3008try {3009do {3010pos = 0;3011if (unread > 0) {3012int n =3013in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));3014if (n >= 0) {3015end = n;3016unread -= n;3017} else {3018throw new StreamCorruptedException(3019"unexpected EOF in middle of data block");3020}3021} else {3022int n = readBlockHeader(true);3023if (n >= 0) {3024end = 0;3025unread = n;3026} else {3027end = -1;3028unread = 0;3029}3030}3031} while (pos == end);3032} catch (IOException ex) {3033pos = 0;3034end = -1;3035unread = 0;3036throw ex;3037}3038}30393040/**3041* If in block data mode, returns the number of unconsumed bytes3042* remaining in the current data block. If not in block data mode,3043* throws an IllegalStateException.3044*/3045int currentBlockRemaining() {3046if (blkmode) {3047return (end >= 0) ? (end - pos) + unread : 0;3048} else {3049throw new IllegalStateException();3050}3051}30523053/**3054* Peeks at (but does not consume) and returns the next byte value in3055* the stream, or -1 if the end of the stream/block data (if in block3056* data mode) has been reached.3057*/3058int peek() throws IOException {3059if (blkmode) {3060if (pos == end) {3061refill();3062}3063return (end >= 0) ? (buf[pos] & 0xFF) : -1;3064} else {3065return in.peek();3066}3067}30683069/**3070* Peeks at (but does not consume) and returns the next byte value in3071* the stream, or throws EOFException if end of stream/block data has3072* been reached.3073*/3074byte peekByte() throws IOException {3075int val = peek();3076if (val < 0) {3077throw new EOFException();3078}3079return (byte) val;3080}308130823083/* ----------------- generic input stream methods ------------------ */3084/*3085* The following methods are equivalent to their counterparts in3086* InputStream, except that they interpret data block boundaries and3087* read the requested data from within data blocks when in block data3088* mode.3089*/30903091public int read() throws IOException {3092if (blkmode) {3093if (pos == end) {3094refill();3095}3096return (end >= 0) ? (buf[pos++] & 0xFF) : -1;3097} else {3098return in.read();3099}3100}31013102public int read(byte[] b, int off, int len) throws IOException {3103return read(b, off, len, false);3104}31053106public long skip(long len) throws IOException {3107long remain = len;3108while (remain > 0) {3109if (blkmode) {3110if (pos == end) {3111refill();3112}3113if (end < 0) {3114break;3115}3116int nread = (int) Math.min(remain, end - pos);3117remain -= nread;3118pos += nread;3119} else {3120int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);3121if ((nread = in.read(buf, 0, nread)) < 0) {3122break;3123}3124remain -= nread;3125}3126}3127return len - remain;3128}31293130public int available() throws IOException {3131if (blkmode) {3132if ((pos == end) && (unread == 0)) {3133int n;3134while ((n = readBlockHeader(false)) == 0) ;3135switch (n) {3136case HEADER_BLOCKED:3137break;31383139case -1:3140pos = 0;3141end = -1;3142break;31433144default:3145pos = 0;3146end = 0;3147unread = n;3148break;3149}3150}3151// avoid unnecessary call to in.available() if possible3152int unreadAvail = (unread > 0) ?3153Math.min(in.available(), unread) : 0;3154return (end >= 0) ? (end - pos) + unreadAvail : 0;3155} else {3156return in.available();3157}3158}31593160public void close() throws IOException {3161if (blkmode) {3162pos = 0;3163end = -1;3164unread = 0;3165}3166in.close();3167}31683169/**3170* Attempts to read len bytes into byte array b at offset off. Returns3171* the number of bytes read, or -1 if the end of stream/block data has3172* been reached. If copy is true, reads values into an intermediate3173* buffer before copying them to b (to avoid exposing a reference to3174* b).3175*/3176int read(byte[] b, int off, int len, boolean copy) throws IOException {3177if (len == 0) {3178return 0;3179} else if (blkmode) {3180if (pos == end) {3181refill();3182}3183if (end < 0) {3184return -1;3185}3186int nread = Math.min(len, end - pos);3187System.arraycopy(buf, pos, b, off, nread);3188pos += nread;3189return nread;3190} else if (copy) {3191int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));3192if (nread > 0) {3193System.arraycopy(buf, 0, b, off, nread);3194}3195return nread;3196} else {3197return in.read(b, off, len);3198}3199}32003201/* ----------------- primitive data input methods ------------------ */3202/*3203* The following methods are equivalent to their counterparts in3204* DataInputStream, except that they interpret data block boundaries3205* and read the requested data from within data blocks when in block3206* data mode.3207*/32083209public void readFully(byte[] b) throws IOException {3210readFully(b, 0, b.length, false);3211}32123213public void readFully(byte[] b, int off, int len) throws IOException {3214readFully(b, off, len, false);3215}32163217public void readFully(byte[] b, int off, int len, boolean copy)3218throws IOException3219{3220while (len > 0) {3221int n = read(b, off, len, copy);3222if (n < 0) {3223throw new EOFException();3224}3225off += n;3226len -= n;3227}3228}32293230public int skipBytes(int n) throws IOException {3231return din.skipBytes(n);3232}32333234public boolean readBoolean() throws IOException {3235int v = read();3236if (v < 0) {3237throw new EOFException();3238}3239return (v != 0);3240}32413242public byte readByte() throws IOException {3243int v = read();3244if (v < 0) {3245throw new EOFException();3246}3247return (byte) v;3248}32493250public int readUnsignedByte() throws IOException {3251int v = read();3252if (v < 0) {3253throw new EOFException();3254}3255return v;3256}32573258public char readChar() throws IOException {3259if (!blkmode) {3260pos = 0;3261in.readFully(buf, 0, 2);3262} else if (end - pos < 2) {3263return din.readChar();3264}3265char v = Bits.getChar(buf, pos);3266pos += 2;3267return v;3268}32693270public short readShort() throws IOException {3271if (!blkmode) {3272pos = 0;3273in.readFully(buf, 0, 2);3274} else if (end - pos < 2) {3275return din.readShort();3276}3277short v = Bits.getShort(buf, pos);3278pos += 2;3279return v;3280}32813282public int readUnsignedShort() throws IOException {3283if (!blkmode) {3284pos = 0;3285in.readFully(buf, 0, 2);3286} else if (end - pos < 2) {3287return din.readUnsignedShort();3288}3289int v = Bits.getShort(buf, pos) & 0xFFFF;3290pos += 2;3291return v;3292}32933294public int readInt() throws IOException {3295if (!blkmode) {3296pos = 0;3297in.readFully(buf, 0, 4);3298} else if (end - pos < 4) {3299return din.readInt();3300}3301int v = Bits.getInt(buf, pos);3302pos += 4;3303return v;3304}33053306public float readFloat() throws IOException {3307if (!blkmode) {3308pos = 0;3309in.readFully(buf, 0, 4);3310} else if (end - pos < 4) {3311return din.readFloat();3312}3313float v = Bits.getFloat(buf, pos);3314pos += 4;3315return v;3316}33173318public long readLong() throws IOException {3319if (!blkmode) {3320pos = 0;3321in.readFully(buf, 0, 8);3322} else if (end - pos < 8) {3323return din.readLong();3324}3325long v = Bits.getLong(buf, pos);3326pos += 8;3327return v;3328}33293330public double readDouble() throws IOException {3331if (!blkmode) {3332pos = 0;3333in.readFully(buf, 0, 8);3334} else if (end - pos < 8) {3335return din.readDouble();3336}3337double v = Bits.getDouble(buf, pos);3338pos += 8;3339return v;3340}33413342public String readUTF() throws IOException {3343return readUTFBody(readUnsignedShort());3344}33453346@SuppressWarnings("deprecation")3347public String readLine() throws IOException {3348return din.readLine(); // deprecated, not worth optimizing3349}33503351/* -------------- primitive data array input methods --------------- */3352/*3353* The following methods read in spans of primitive data values.3354* Though equivalent to calling the corresponding primitive read3355* methods repeatedly, these methods are optimized for reading groups3356* of primitive data values more efficiently.3357*/33583359void readBooleans(boolean[] v, int off, int len) throws IOException {3360int stop, endoff = off + len;3361while (off < endoff) {3362if (!blkmode) {3363int span = Math.min(endoff - off, MAX_BLOCK_SIZE);3364in.readFully(buf, 0, span);3365stop = off + span;3366pos = 0;3367} else if (end - pos < 1) {3368v[off++] = din.readBoolean();3369continue;3370} else {3371stop = Math.min(endoff, off + end - pos);3372}33733374while (off < stop) {3375v[off++] = Bits.getBoolean(buf, pos++);3376}3377}3378}33793380void readChars(char[] v, int off, int len) throws IOException {3381int stop, endoff = off + len;3382while (off < endoff) {3383if (!blkmode) {3384int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);3385in.readFully(buf, 0, span << 1);3386stop = off + span;3387pos = 0;3388} else if (end - pos < 2) {3389v[off++] = din.readChar();3390continue;3391} else {3392stop = Math.min(endoff, off + ((end - pos) >> 1));3393}33943395while (off < stop) {3396v[off++] = Bits.getChar(buf, pos);3397pos += 2;3398}3399}3400}34013402void readShorts(short[] v, int off, int len) throws IOException {3403int stop, endoff = off + len;3404while (off < endoff) {3405if (!blkmode) {3406int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);3407in.readFully(buf, 0, span << 1);3408stop = off + span;3409pos = 0;3410} else if (end - pos < 2) {3411v[off++] = din.readShort();3412continue;3413} else {3414stop = Math.min(endoff, off + ((end - pos) >> 1));3415}34163417while (off < stop) {3418v[off++] = Bits.getShort(buf, pos);3419pos += 2;3420}3421}3422}34233424void readInts(int[] v, int off, int len) throws IOException {3425int stop, endoff = off + len;3426while (off < endoff) {3427if (!blkmode) {3428int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);3429in.readFully(buf, 0, span << 2);3430stop = off + span;3431pos = 0;3432} else if (end - pos < 4) {3433v[off++] = din.readInt();3434continue;3435} else {3436stop = Math.min(endoff, off + ((end - pos) >> 2));3437}34383439while (off < stop) {3440v[off++] = Bits.getInt(buf, pos);3441pos += 4;3442}3443}3444}34453446void readFloats(float[] v, int off, int len) throws IOException {3447int span, endoff = off + len;3448while (off < endoff) {3449if (!blkmode) {3450span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);3451in.readFully(buf, 0, span << 2);3452pos = 0;3453} else if (end - pos < 4) {3454v[off++] = din.readFloat();3455continue;3456} else {3457span = Math.min(endoff - off, ((end - pos) >> 2));3458}34593460bytesToFloats(buf, pos, v, off, span);3461off += span;3462pos += span << 2;3463}3464}34653466void readLongs(long[] v, int off, int len) throws IOException {3467int stop, endoff = off + len;3468while (off < endoff) {3469if (!blkmode) {3470int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);3471in.readFully(buf, 0, span << 3);3472stop = off + span;3473pos = 0;3474} else if (end - pos < 8) {3475v[off++] = din.readLong();3476continue;3477} else {3478stop = Math.min(endoff, off + ((end - pos) >> 3));3479}34803481while (off < stop) {3482v[off++] = Bits.getLong(buf, pos);3483pos += 8;3484}3485}3486}34873488void readDoubles(double[] v, int off, int len) throws IOException {3489int span, endoff = off + len;3490while (off < endoff) {3491if (!blkmode) {3492span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);3493in.readFully(buf, 0, span << 3);3494pos = 0;3495} else if (end - pos < 8) {3496v[off++] = din.readDouble();3497continue;3498} else {3499span = Math.min(endoff - off, ((end - pos) >> 3));3500}35013502bytesToDoubles(buf, pos, v, off, span);3503off += span;3504pos += span << 3;3505}3506}35073508/**3509* Reads in string written in "long" UTF format. "Long" UTF format is3510* identical to standard UTF, except that it uses an 8 byte header3511* (instead of the standard 2 bytes) to convey the UTF encoding length.3512*/3513String readLongUTF() throws IOException {3514return readUTFBody(readLong());3515}35163517/**3518* Reads in the "body" (i.e., the UTF representation minus the 2-byte3519* or 8-byte length header) of a UTF encoding, which occupies the next3520* utflen bytes.3521*/3522private String readUTFBody(long utflen) throws IOException {3523StringBuilder sbuf;3524if (utflen > 0 && utflen < Integer.MAX_VALUE) {3525// a reasonable initial capacity based on the UTF length3526int initialCapacity = Math.min((int)utflen, 0xFFFF);3527sbuf = new StringBuilder(initialCapacity);3528} else {3529sbuf = new StringBuilder();3530}35313532if (!blkmode) {3533end = pos = 0;3534}35353536while (utflen > 0) {3537int avail = end - pos;3538if (avail >= 3 || (long) avail == utflen) {3539utflen -= readUTFSpan(sbuf, utflen);3540} else {3541if (blkmode) {3542// near block boundary, read one byte at a time3543utflen -= readUTFChar(sbuf, utflen);3544} else {3545// shift and refill buffer manually3546if (avail > 0) {3547System.arraycopy(buf, pos, buf, 0, avail);3548}3549pos = 0;3550end = (int) Math.min(MAX_BLOCK_SIZE, utflen);3551in.readFully(buf, avail, end - avail);3552}3553}3554}35553556return sbuf.toString();3557}35583559/**3560* Reads span of UTF-encoded characters out of internal buffer3561* (starting at offset pos and ending at or before offset end),3562* consuming no more than utflen bytes. Appends read characters to3563* sbuf. Returns the number of bytes consumed.3564*/3565private long readUTFSpan(StringBuilder sbuf, long utflen)3566throws IOException3567{3568int cpos = 0;3569int start = pos;3570int avail = Math.min(end - pos, CHAR_BUF_SIZE);3571// stop short of last char unless all of utf bytes in buffer3572int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);3573boolean outOfBounds = false;35743575try {3576while (pos < stop) {3577int b1, b2, b3;3578b1 = buf[pos++] & 0xFF;3579switch (b1 >> 4) {3580case 0:3581case 1:3582case 2:3583case 3:3584case 4:3585case 5:3586case 6:3587case 7: // 1 byte format: 0xxxxxxx3588cbuf[cpos++] = (char) b1;3589break;35903591case 12:3592case 13: // 2 byte format: 110xxxxx 10xxxxxx3593b2 = buf[pos++];3594if ((b2 & 0xC0) != 0x80) {3595throw new UTFDataFormatException();3596}3597cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |3598((b2 & 0x3F) << 0));3599break;36003601case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx3602b3 = buf[pos + 1];3603b2 = buf[pos + 0];3604pos += 2;3605if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {3606throw new UTFDataFormatException();3607}3608cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |3609((b2 & 0x3F) << 6) |3610((b3 & 0x3F) << 0));3611break;36123613default: // 10xx xxxx, 1111 xxxx3614throw new UTFDataFormatException();3615}3616}3617} catch (ArrayIndexOutOfBoundsException ex) {3618outOfBounds = true;3619} finally {3620if (outOfBounds || (pos - start) > utflen) {3621/*3622* Fix for 4450867: if a malformed utf char causes the3623* conversion loop to scan past the expected end of the utf3624* string, only consume the expected number of utf bytes.3625*/3626pos = start + (int) utflen;3627throw new UTFDataFormatException();3628}3629}36303631sbuf.append(cbuf, 0, cpos);3632return pos - start;3633}36343635/**3636* Reads in single UTF-encoded character one byte at a time, appends3637* the character to sbuf, and returns the number of bytes consumed.3638* This method is used when reading in UTF strings written in block3639* data mode to handle UTF-encoded characters which (potentially)3640* straddle block-data boundaries.3641*/3642private int readUTFChar(StringBuilder sbuf, long utflen)3643throws IOException3644{3645int b1, b2, b3;3646b1 = readByte() & 0xFF;3647switch (b1 >> 4) {3648case 0:3649case 1:3650case 2:3651case 3:3652case 4:3653case 5:3654case 6:3655case 7: // 1 byte format: 0xxxxxxx3656sbuf.append((char) b1);3657return 1;36583659case 12:3660case 13: // 2 byte format: 110xxxxx 10xxxxxx3661if (utflen < 2) {3662throw new UTFDataFormatException();3663}3664b2 = readByte();3665if ((b2 & 0xC0) != 0x80) {3666throw new UTFDataFormatException();3667}3668sbuf.append((char) (((b1 & 0x1F) << 6) |3669((b2 & 0x3F) << 0)));3670return 2;36713672case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx3673if (utflen < 3) {3674if (utflen == 2) {3675readByte(); // consume remaining byte3676}3677throw new UTFDataFormatException();3678}3679b2 = readByte();3680b3 = readByte();3681if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {3682throw new UTFDataFormatException();3683}3684sbuf.append((char) (((b1 & 0x0F) << 12) |3685((b2 & 0x3F) << 6) |3686((b3 & 0x3F) << 0)));3687return 3;36883689default: // 10xx xxxx, 1111 xxxx3690throw new UTFDataFormatException();3691}3692}36933694/**3695* Returns the number of bytes read from the input stream.3696* @return the number of bytes read from the input stream3697*/3698long getBytesRead() {3699return in.getBytesRead();3700}3701}37023703/**3704* Unsynchronized table which tracks wire handle to object mappings, as3705* well as ClassNotFoundExceptions associated with deserialized objects.3706* This class implements an exception-propagation algorithm for3707* determining which objects should have ClassNotFoundExceptions associated3708* with them, taking into account cycles and discontinuities (e.g., skipped3709* fields) in the object graph.3710*3711* <p>General use of the table is as follows: during deserialization, a3712* given object is first assigned a handle by calling the assign method.3713* This method leaves the assigned handle in an "open" state, wherein3714* dependencies on the exception status of other handles can be registered3715* by calling the markDependency method, or an exception can be directly3716* associated with the handle by calling markException. When a handle is3717* tagged with an exception, the HandleTable assumes responsibility for3718* propagating the exception to any other objects which depend3719* (transitively) on the exception-tagged object.3720*3721* <p>Once all exception information/dependencies for the handle have been3722* registered, the handle should be "closed" by calling the finish method3723* on it. The act of finishing a handle allows the exception propagation3724* algorithm to aggressively prune dependency links, lessening the3725* performance/memory impact of exception tracking.3726*3727* <p>Note that the exception propagation algorithm used depends on handles3728* being assigned/finished in LIFO order; however, for simplicity as well3729* as memory conservation, it does not enforce this constraint.3730*/3731// REMIND: add full description of exception propagation algorithm?3732private static class HandleTable {37333734/* status codes indicating whether object has associated exception */3735private static final byte STATUS_OK = 1;3736private static final byte STATUS_UNKNOWN = 2;3737private static final byte STATUS_EXCEPTION = 3;37383739/** array mapping handle -> object status */3740byte[] status;3741/** array mapping handle -> object/exception (depending on status) */3742Object[] entries;3743/** array mapping handle -> list of dependent handles (if any) */3744HandleList[] deps;3745/** lowest unresolved dependency */3746int lowDep = -1;3747/** number of handles in table */3748int size = 0;37493750/**3751* Creates handle table with the given initial capacity.3752*/3753HandleTable(int initialCapacity) {3754status = new byte[initialCapacity];3755entries = new Object[initialCapacity];3756deps = new HandleList[initialCapacity];3757}37583759/**3760* Assigns next available handle to given object, and returns assigned3761* handle. Once object has been completely deserialized (and all3762* dependencies on other objects identified), the handle should be3763* "closed" by passing it to finish().3764*/3765int assign(Object obj) {3766if (size >= entries.length) {3767grow();3768}3769status[size] = STATUS_UNKNOWN;3770entries[size] = obj;3771return size++;3772}37733774/**3775* Registers a dependency (in exception status) of one handle on3776* another. The dependent handle must be "open" (i.e., assigned, but3777* not finished yet). No action is taken if either dependent or target3778* handle is NULL_HANDLE.3779*/3780void markDependency(int dependent, int target) {3781if (dependent == NULL_HANDLE || target == NULL_HANDLE) {3782return;3783}3784switch (status[dependent]) {37853786case STATUS_UNKNOWN:3787switch (status[target]) {3788case STATUS_OK:3789// ignore dependencies on objs with no exception3790break;37913792case STATUS_EXCEPTION:3793// eagerly propagate exception3794markException(dependent,3795(ClassNotFoundException) entries[target]);3796break;37973798case STATUS_UNKNOWN:3799// add to dependency list of target3800if (deps[target] == null) {3801deps[target] = new HandleList();3802}3803deps[target].add(dependent);38043805// remember lowest unresolved target seen3806if (lowDep < 0 || lowDep > target) {3807lowDep = target;3808}3809break;38103811default:3812throw new InternalError();3813}3814break;38153816case STATUS_EXCEPTION:3817break;38183819default:3820throw new InternalError();3821}3822}38233824/**3825* Associates a ClassNotFoundException (if one not already associated)3826* with the currently active handle and propagates it to other3827* referencing objects as appropriate. The specified handle must be3828* "open" (i.e., assigned, but not finished yet).3829*/3830void markException(int handle, ClassNotFoundException ex) {3831switch (status[handle]) {3832case STATUS_UNKNOWN:3833status[handle] = STATUS_EXCEPTION;3834entries[handle] = ex;38353836// propagate exception to dependents3837HandleList dlist = deps[handle];3838if (dlist != null) {3839int ndeps = dlist.size();3840for (int i = 0; i < ndeps; i++) {3841markException(dlist.get(i), ex);3842}3843deps[handle] = null;3844}3845break;38463847case STATUS_EXCEPTION:3848break;38493850default:3851throw new InternalError();3852}3853}38543855/**3856* Marks given handle as finished, meaning that no new dependencies3857* will be marked for handle. Calls to the assign and finish methods3858* must occur in LIFO order.3859*/3860void finish(int handle) {3861int end;3862if (lowDep < 0) {3863// no pending unknowns, only resolve current handle3864end = handle + 1;3865} else if (lowDep >= handle) {3866// pending unknowns now clearable, resolve all upward handles3867end = size;3868lowDep = -1;3869} else {3870// unresolved backrefs present, can't resolve anything yet3871return;3872}38733874// change STATUS_UNKNOWN -> STATUS_OK in selected span of handles3875for (int i = handle; i < end; i++) {3876switch (status[i]) {3877case STATUS_UNKNOWN:3878status[i] = STATUS_OK;3879deps[i] = null;3880break;38813882case STATUS_OK:3883case STATUS_EXCEPTION:3884break;38853886default:3887throw new InternalError();3888}3889}3890}38913892/**3893* Assigns a new object to the given handle. The object previously3894* associated with the handle is forgotten. This method has no effect3895* if the given handle already has an exception associated with it.3896* This method may be called at any time after the handle is assigned.3897*/3898void setObject(int handle, Object obj) {3899switch (status[handle]) {3900case STATUS_UNKNOWN:3901case STATUS_OK:3902entries[handle] = obj;3903break;39043905case STATUS_EXCEPTION:3906break;39073908default:3909throw new InternalError();3910}3911}39123913/**3914* Looks up and returns object associated with the given handle.3915* Returns null if the given handle is NULL_HANDLE, or if it has an3916* associated ClassNotFoundException.3917*/3918Object lookupObject(int handle) {3919return (handle != NULL_HANDLE &&3920status[handle] != STATUS_EXCEPTION) ?3921entries[handle] : null;3922}39233924/**3925* Looks up and returns ClassNotFoundException associated with the3926* given handle. Returns null if the given handle is NULL_HANDLE, or3927* if there is no ClassNotFoundException associated with the handle.3928*/3929ClassNotFoundException lookupException(int handle) {3930return (handle != NULL_HANDLE &&3931status[handle] == STATUS_EXCEPTION) ?3932(ClassNotFoundException) entries[handle] : null;3933}39343935/**3936* Resets table to its initial state.3937*/3938void clear() {3939Arrays.fill(status, 0, size, (byte) 0);3940Arrays.fill(entries, 0, size, null);3941Arrays.fill(deps, 0, size, null);3942lowDep = -1;3943size = 0;3944}39453946/**3947* Returns number of handles registered in table.3948*/3949int size() {3950return size;3951}39523953/**3954* Expands capacity of internal arrays.3955*/3956private void grow() {3957int newCapacity = (entries.length << 1) + 1;39583959byte[] newStatus = new byte[newCapacity];3960Object[] newEntries = new Object[newCapacity];3961HandleList[] newDeps = new HandleList[newCapacity];39623963System.arraycopy(status, 0, newStatus, 0, size);3964System.arraycopy(entries, 0, newEntries, 0, size);3965System.arraycopy(deps, 0, newDeps, 0, size);39663967status = newStatus;3968entries = newEntries;3969deps = newDeps;3970}39713972/**3973* Simple growable list of (integer) handles.3974*/3975private static class HandleList {3976private int[] list = new int[4];3977private int size = 0;39783979public HandleList() {3980}39813982public void add(int handle) {3983if (size >= list.length) {3984int[] newList = new int[list.length << 1];3985System.arraycopy(list, 0, newList, 0, list.length);3986list = newList;3987}3988list[size++] = handle;3989}39903991public int get(int index) {3992if (index >= size) {3993throw new ArrayIndexOutOfBoundsException();3994}3995return list[index];3996}39973998public int size() {3999return size;4000}4001}4002}40034004/**4005* Method for cloning arrays in case of using unsharing reading4006*/4007private static Object cloneArray(Object array) {4008if (array instanceof Object[]) {4009return ((Object[]) array).clone();4010} else if (array instanceof boolean[]) {4011return ((boolean[]) array).clone();4012} else if (array instanceof byte[]) {4013return ((byte[]) array).clone();4014} else if (array instanceof char[]) {4015return ((char[]) array).clone();4016} else if (array instanceof double[]) {4017return ((double[]) array).clone();4018} else if (array instanceof float[]) {4019return ((float[]) array).clone();4020} else if (array instanceof int[]) {4021return ((int[]) array).clone();4022} else if (array instanceof long[]) {4023return ((long[]) array).clone();4024} else if (array instanceof short[]) {4025return ((short[]) array).clone();4026} else {4027throw new AssertionError();4028}4029}40304031private void validateDescriptor(ObjectStreamClass descriptor) {4032ObjectStreamClassValidator validating = validator;4033if (validating != null) {4034validating.validateDescriptor(descriptor);4035}4036}40374038// controlled access to ObjectStreamClassValidator4039private volatile ObjectStreamClassValidator validator;40404041private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {4042ois.validator = validator;4043}4044static {4045SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);4046SharedSecrets.setJavaObjectInputStreamReadString(ObjectInputStream::readString);4047}4048}404940504051