Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/io/ObjectInputStream.java
38829 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.ObjectInputFilter;47import sun.misc.ObjectStreamClassValidator;48import sun.misc.SharedSecrets;49import sun.reflect.misc.ReflectUtil;50import sun.misc.JavaOISAccess;51import sun.util.logging.PlatformLogger;52import sun.security.action.GetBooleanAction;53import sun.security.action.GetIntegerAction;5455/**56* An ObjectInputStream deserializes primitive data and objects previously57* written using an ObjectOutputStream.58*59* <p>ObjectOutputStream and ObjectInputStream can provide an application with60* persistent storage for graphs of objects when used with a FileOutputStream61* and FileInputStream respectively. ObjectInputStream is used to recover62* those objects previously serialized. Other uses include passing objects63* between hosts using a socket stream or for marshaling and unmarshaling64* arguments and parameters in a remote communication system.65*66* <p>ObjectInputStream ensures that the types of all objects in the graph67* created from the stream match the classes present in the Java Virtual68* Machine. Classes are loaded as required using the standard mechanisms.69*70* <p>Only objects that support the java.io.Serializable or71* java.io.Externalizable interface can be read from streams.72*73* <p>The method <code>readObject</code> is used to read an object from the74* stream. Java's safe casting should be used to get the desired type. In75* Java, strings and arrays are objects and are treated as objects during76* serialization. When read they need to be cast to the expected type.77*78* <p>Primitive data types can be read from the stream using the appropriate79* method on DataInput.80*81* <p>The default deserialization mechanism for objects restores the contents82* of each field to the value and type it had when it was written. Fields83* declared as transient or static are ignored by the deserialization process.84* References to other objects cause those objects to be read from the stream85* as necessary. Graphs of objects are restored correctly using a reference86* sharing mechanism. New objects are always allocated when deserializing,87* which prevents existing objects from being overwritten.88*89* <p>Reading an object is analogous to running the constructors of a new90* object. Memory is allocated for the object and initialized to zero (NULL).91* No-arg constructors are invoked for the non-serializable classes and then92* the fields of the serializable classes are restored from the stream starting93* with the serializable class closest to java.lang.object and finishing with94* the object's most specific class.95*96* <p>For example to read from a stream as written by the example in97* ObjectOutputStream:98* <br>99* <pre>100* FileInputStream fis = new FileInputStream("t.tmp");101* ObjectInputStream ois = new ObjectInputStream(fis);102*103* int i = ois.readInt();104* String today = (String) ois.readObject();105* Date date = (Date) ois.readObject();106*107* ois.close();108* </pre>109*110* <p>Classes control how they are serialized by implementing either the111* java.io.Serializable or java.io.Externalizable interfaces.112*113* <p>Implementing the Serializable interface allows object serialization to114* save and restore the entire state of the object and it allows classes to115* evolve between the time the stream is written and the time it is read. It116* automatically traverses references between objects, saving and restoring117* entire graphs.118*119* <p>Serializable classes that require special handling during the120* serialization and deserialization process should implement the following121* methods:122*123* <pre>124* private void writeObject(java.io.ObjectOutputStream stream)125* throws IOException;126* private void readObject(java.io.ObjectInputStream stream)127* throws IOException, ClassNotFoundException;128* private void readObjectNoData()129* throws ObjectStreamException;130* </pre>131*132* <p>The readObject method is responsible for reading and restoring the state133* of the object for its particular class using data written to the stream by134* the corresponding writeObject method. The method does not need to concern135* itself with the state belonging to its superclasses or subclasses. State is136* restored by reading data from the ObjectInputStream for the individual137* fields and making assignments to the appropriate fields of the object.138* Reading primitive data types is supported by DataInput.139*140* <p>Any attempt to read object data which exceeds the boundaries of the141* custom data written by the corresponding writeObject method will cause an142* OptionalDataException to be thrown with an eof field value of true.143* Non-object reads which exceed the end of the allotted data will reflect the144* end of data in the same way that they would indicate the end of the stream:145* bytewise reads will return -1 as the byte read or number of bytes read, and146* primitive reads will throw EOFExceptions. If there is no corresponding147* writeObject method, then the end of default serialized data marks the end of148* the allotted data.149*150* <p>Primitive and object read calls issued from within a readExternal method151* behave in the same manner--if the stream is already positioned at the end of152* data written by the corresponding writeExternal method, object reads will153* throw OptionalDataExceptions with eof set to true, bytewise reads will154* return -1, and primitive reads will throw EOFExceptions. Note that this155* behavior does not hold for streams written with the old156* <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the157* end of data written by writeExternal methods is not demarcated, and hence158* cannot be detected.159*160* <p>The readObjectNoData method is responsible for initializing the state of161* the object for its particular class in the event that the serialization162* stream does not list the given class as a superclass of the object being163* deserialized. This may occur in cases where the receiving party uses a164* different version of the deserialized instance's class than the sending165* party, and the receiver's version extends classes that are not extended by166* the sender's version. This may also occur if the serialization stream has167* been tampered; hence, readObjectNoData is useful for initializing168* deserialized objects properly despite a "hostile" or incomplete source169* stream.170*171* <p>Serialization does not read or assign values to the fields of any object172* that does not implement the java.io.Serializable interface. Subclasses of173* Objects that are not serializable can be serializable. In this case the174* non-serializable class must have a no-arg constructor to allow its fields to175* be initialized. In this case it is the responsibility of the subclass to176* save and restore the state of the non-serializable class. It is frequently177* the case that the fields of that class are accessible (public, package, or178* protected) or that there are get and set methods that can be used to restore179* the state.180*181* <p>Any exception that occurs while deserializing an object will be caught by182* the ObjectInputStream and abort the reading process.183*184* <p>Implementing the Externalizable interface allows the object to assume185* complete control over the contents and format of the object's serialized186* form. The methods of the Externalizable interface, writeExternal and187* readExternal, are called to save and restore the objects state. When188* implemented by a class they can write and read their own state using all of189* the methods of ObjectOutput and ObjectInput. It is the responsibility of190* the objects to handle any versioning that occurs.191*192* <p>Enum constants are deserialized differently than ordinary serializable or193* externalizable objects. The serialized form of an enum constant consists194* solely of its name; field values of the constant are not transmitted. To195* deserialize an enum constant, ObjectInputStream reads the constant name from196* the stream; the deserialized constant is then obtained by calling the static197* method <code>Enum.valueOf(Class, String)</code> with the enum constant's198* base type and the received constant name as arguments. Like other199* serializable or externalizable objects, enum constants can function as the200* targets of back references appearing subsequently in the serialization201* stream. The process by which enum constants are deserialized cannot be202* customized: any class-specific readObject, readObjectNoData, and readResolve203* methods defined by enum types are ignored during deserialization.204* Similarly, any serialPersistentFields or serialVersionUID field declarations205* are also ignored--all enum types have a fixed serialVersionUID of 0L.206*207* @author Mike Warres208* @author Roger Riggs209* @see java.io.DataInput210* @see java.io.ObjectOutputStream211* @see java.io.Serializable212* @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>213* @since JDK1.1214*/215public class ObjectInputStream216extends InputStream implements ObjectInput, ObjectStreamConstants217{218/** handle value representing null */219private static final int NULL_HANDLE = -1;220221/** marker for unshared objects in internal handle table */222private static final Object unsharedMarker = new Object();223224/** table mapping primitive type names to corresponding class objects */225private static final HashMap<String, Class<?>> primClasses226= new HashMap<>(8, 1.0F);227static {228primClasses.put("boolean", boolean.class);229primClasses.put("byte", byte.class);230primClasses.put("char", char.class);231primClasses.put("short", short.class);232primClasses.put("int", int.class);233primClasses.put("long", long.class);234primClasses.put("float", float.class);235primClasses.put("double", double.class);236primClasses.put("void", void.class);237}238239private static class Caches {240/** cache of subclass security audit results */241static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =242new ConcurrentHashMap<>();243244/** queue for WeakReferences to audited subclasses */245static final ReferenceQueue<Class<?>> subclassAuditsQueue =246new ReferenceQueue<>();247248/**249* Property to permit setting a filter after objects250* have been read.251* See {@link #setObjectInputFilter(ObjectInputFilter)}252*/253static final boolean SET_FILTER_AFTER_READ =254privilegedGetProperty("jdk.serialSetFilterAfterRead");255256/**257* Property to override the implementation limit on the number258* of interfaces allowed for Proxies. The property value is clamped to 0..65535.259* The maximum number of interfaces allowed for a proxy is limited to 65535 by260* {@link java.lang.reflect.Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)}261*/262static final int PROXY_INTERFACE_LIMIT = Math.max(0, Math.min(65535,263privilegedGetIntegerProperty("jdk.serialProxyInterfaceLimit", 65535)));264265private static boolean privilegedGetProperty(String theProp) {266if (System.getSecurityManager() == null) {267return Boolean.getBoolean(theProp);268} else {269return AccessController.doPrivileged(270new GetBooleanAction(theProp));271}272}273274private static int privilegedGetIntegerProperty(String theProp, int defaultValue) {275if (System.getSecurityManager() == null) {276return Integer.getInteger(theProp, defaultValue);277} else {278return AccessController.doPrivileged(279new GetIntegerAction(theProp, defaultValue));280}281}282}283284static {285/* Setup access so sun.misc can invoke package private functions. */286JavaOISAccess javaOISAccess = new JavaOISAccess() {287public void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter) {288stream.setInternalObjectInputFilter(filter);289}290291public ObjectInputFilter getObjectInputFilter(ObjectInputStream stream) {292return stream.getInternalObjectInputFilter();293}294295public void checkArray(ObjectInputStream stream, Class<?> arrayType, int arrayLength)296throws InvalidClassException297{298stream.checkArray(arrayType, arrayLength);299}300};301302sun.misc.SharedSecrets.setJavaOISAccess(javaOISAccess);303}304305/*306* Separate class to defer initialization of logging until needed.307*/308private static class Logging {309310/*311* Logger for ObjectInputFilter results.312* Setup the filter logger if it is set to INFO or WARNING.313* (Assuming it will not change).314*/315private static final PlatformLogger traceLogger;316private static final PlatformLogger infoLogger;317static {318PlatformLogger filterLog = PlatformLogger.getLogger("java.io.serialization");319infoLogger = (filterLog != null &&320filterLog.isLoggable(PlatformLogger.Level.INFO)) ? filterLog : null;321traceLogger = (filterLog != null &&322filterLog.isLoggable(PlatformLogger.Level.FINER)) ? filterLog : null;323}324}325326/** filter stream for handling block data conversion */327private final BlockDataInputStream bin;328/** validation callback list */329private final ValidationList vlist;330/** recursion depth */331private long depth;332/** Total number of references to any type of object, class, enum, proxy, etc. */333private long totalObjectRefs;334/** whether stream is closed */335private boolean closed;336337/** wire handle -> obj/exception map */338private final HandleTable handles;339/** scratch field for passing handle values up/down call stack */340private int passHandle = NULL_HANDLE;341/** flag set when at end of field value block with no TC_ENDBLOCKDATA */342private boolean defaultDataEnd = false;343344/** buffer for reading primitive field values */345private byte[] primVals;346347/** if true, invoke readObjectOverride() instead of readObject() */348private final boolean enableOverride;349/** if true, invoke resolveObject() */350private boolean enableResolve;351352/**353* Context during upcalls to class-defined readObject methods; holds354* object currently being deserialized and descriptor for current class.355* Null when not during readObject upcall.356*/357private SerialCallbackContext curContext;358359/**360* Filter of class descriptors and classes read from the stream;361* may be null.362*/363private ObjectInputFilter serialFilter;364365/**366* Creates an ObjectInputStream that reads from the specified InputStream.367* A serialization stream header is read from the stream and verified.368* This constructor will block until the corresponding ObjectOutputStream369* has written and flushed the header.370*371* <p>If a security manager is installed, this constructor will check for372* the "enableSubclassImplementation" SerializablePermission when invoked373* directly or indirectly by the constructor of a subclass which overrides374* the ObjectInputStream.readFields or ObjectInputStream.readUnshared375* methods.376*377* @param in input stream to read from378* @throws StreamCorruptedException if the stream header is incorrect379* @throws IOException if an I/O error occurs while reading stream header380* @throws SecurityException if untrusted subclass illegally overrides381* security-sensitive methods382* @throws NullPointerException if <code>in</code> is <code>null</code>383* @see ObjectInputStream#ObjectInputStream()384* @see ObjectInputStream#readFields()385* @see ObjectOutputStream#ObjectOutputStream(OutputStream)386*/387public ObjectInputStream(InputStream in) throws IOException {388verifySubclass();389bin = new BlockDataInputStream(in);390handles = new HandleTable(10);391vlist = new ValidationList();392serialFilter = ObjectInputFilter.Config.getSerialFilter();393enableOverride = false;394readStreamHeader();395bin.setBlockDataMode(true);396}397398/**399* Provide a way for subclasses that are completely reimplementing400* ObjectInputStream to not have to allocate private data just used by this401* implementation of ObjectInputStream.402*403* <p>If there is a security manager installed, this method first calls the404* security manager's <code>checkPermission</code> method with the405* <code>SerializablePermission("enableSubclassImplementation")</code>406* permission to ensure it's ok to enable subclassing.407*408* @throws SecurityException if a security manager exists and its409* <code>checkPermission</code> method denies enabling410* subclassing.411* @throws IOException if an I/O error occurs while creating this stream412* @see SecurityManager#checkPermission413* @see java.io.SerializablePermission414*/415protected ObjectInputStream() throws IOException, SecurityException {416SecurityManager sm = System.getSecurityManager();417if (sm != null) {418sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);419}420bin = null;421handles = null;422vlist = null;423serialFilter = ObjectInputFilter.Config.getSerialFilter();424enableOverride = true;425}426427/**428* Read an object from the ObjectInputStream. The class of the object, the429* signature of the class, and the values of the non-transient and430* non-static fields of the class and all of its supertypes are read.431* Default deserializing for a class can be overridden using the writeObject432* and readObject methods. Objects referenced by this object are read433* transitively so that a complete equivalent graph of objects is434* reconstructed by readObject.435*436* <p>The root object is completely restored when all of its fields and the437* objects it references are completely restored. At this point the object438* validation callbacks are executed in order based on their registered439* priorities. The callbacks are registered by objects (in the readObject440* special methods) as they are individually restored.441*442* <p>Exceptions are thrown for problems with the InputStream and for443* classes that should not be deserialized. All exceptions are fatal to444* the InputStream and leave it in an indeterminate state; it is up to the445* caller to ignore or recover the stream state.446*447* @throws ClassNotFoundException Class of a serialized object cannot be448* found.449* @throws InvalidClassException Something is wrong with a class used by450* serialization.451* @throws StreamCorruptedException Control information in the452* stream is inconsistent.453* @throws OptionalDataException Primitive data was found in the454* stream instead of objects.455* @throws IOException Any of the usual Input/Output related exceptions.456*/457public final Object readObject()458throws IOException, ClassNotFoundException {459return readObject(Object.class);460}461462/**463* Reads a String and only a string.464*465* @return the String read466* @throws EOFException If end of file is reached.467* @throws IOException If other I/O error has occurred.468*/469private String readString() throws IOException {470try {471return (String) readObject(String.class);472} catch (ClassNotFoundException cnf) {473throw new IllegalStateException(cnf);474}475}476477/**478* Internal method to read an object from the ObjectInputStream of the expected type.479* Called only from {@code readObject()} and {@code readString()}.480* Only {@code Object.class} and {@code String.class} are supported.481*482* @param type the type expected; either Object.class or String.class483* @return an object of the type484* @throws IOException Any of the usual Input/Output related exceptions.485* @throws ClassNotFoundException Class of a serialized object cannot be486* found.487*/488private final Object readObject(Class<?> type)489throws IOException, ClassNotFoundException490{491if (enableOverride) {492return readObjectOverride();493}494495if (! (type == Object.class || type == String.class))496throw new AssertionError("internal error");497498// if nested read, passHandle contains handle of enclosing object499int outerHandle = passHandle;500try {501Object obj = readObject0(type, false);502handles.markDependency(outerHandle, passHandle);503ClassNotFoundException ex = handles.lookupException(passHandle);504if (ex != null) {505throw ex;506}507if (depth == 0) {508vlist.doCallbacks();509}510return obj;511} finally {512passHandle = outerHandle;513if (closed && depth == 0) {514clear();515}516}517}518519/**520* This method is called by trusted subclasses of ObjectOutputStream that521* constructed ObjectOutputStream using the protected no-arg constructor.522* The subclass is expected to provide an override method with the modifier523* "final".524*525* @return the Object read from the stream.526* @throws ClassNotFoundException Class definition of a serialized object527* cannot be found.528* @throws OptionalDataException Primitive data was found in the stream529* instead of objects.530* @throws IOException if I/O errors occurred while reading from the531* underlying stream532* @see #ObjectInputStream()533* @see #readObject()534* @since 1.2535*/536protected Object readObjectOverride()537throws IOException, ClassNotFoundException538{539return null;540}541542/**543* Reads an "unshared" object from the ObjectInputStream. This method is544* identical to readObject, except that it prevents subsequent calls to545* readObject and readUnshared from returning additional references to the546* deserialized instance obtained via this call. Specifically:547* <ul>548* <li>If readUnshared is called to deserialize a back-reference (the549* stream representation of an object which has been written550* previously to the stream), an ObjectStreamException will be551* thrown.552*553* <li>If readUnshared returns successfully, then any subsequent attempts554* to deserialize back-references to the stream handle deserialized555* by readUnshared will cause an ObjectStreamException to be thrown.556* </ul>557* Deserializing an object via readUnshared invalidates the stream handle558* associated with the returned object. Note that this in itself does not559* always guarantee that the reference returned by readUnshared is unique;560* the deserialized object may define a readResolve method which returns an561* object visible to other parties, or readUnshared may return a Class562* object or enum constant obtainable elsewhere in the stream or through563* external means. If the deserialized object defines a readResolve method564* and the invocation of that method returns an array, then readUnshared565* returns a shallow clone of that array; this guarantees that the returned566* array object is unique and cannot be obtained a second time from an567* invocation of readObject or readUnshared on the ObjectInputStream,568* even if the underlying data stream has been manipulated.569*570* <p>ObjectInputStream subclasses which override this method can only be571* constructed in security contexts possessing the572* "enableSubclassImplementation" SerializablePermission; any attempt to573* instantiate such a subclass without this permission will cause a574* SecurityException to be thrown.575*576* @return reference to deserialized object577* @throws ClassNotFoundException if class of an object to deserialize578* cannot be found579* @throws StreamCorruptedException if control information in the stream580* is inconsistent581* @throws ObjectStreamException if object to deserialize has already582* appeared in stream583* @throws OptionalDataException if primitive data is next in stream584* @throws IOException if an I/O error occurs during deserialization585* @since 1.4586*/587public Object readUnshared() throws IOException, ClassNotFoundException {588// if nested read, passHandle contains handle of enclosing object589int outerHandle = passHandle;590try {591Object obj = readObject0(Object.class, true);592handles.markDependency(outerHandle, passHandle);593ClassNotFoundException ex = handles.lookupException(passHandle);594if (ex != null) {595throw ex;596}597if (depth == 0) {598vlist.doCallbacks();599}600return obj;601} finally {602passHandle = outerHandle;603if (closed && depth == 0) {604clear();605}606}607}608609/**610* Read the non-static and non-transient fields of the current class from611* this stream. This may only be called from the readObject method of the612* class being deserialized. It will throw the NotActiveException if it is613* called otherwise.614*615* @throws ClassNotFoundException if the class of a serialized object616* could not be found.617* @throws IOException if an I/O error occurs.618* @throws NotActiveException if the stream is not currently reading619* objects.620*/621public void defaultReadObject()622throws IOException, ClassNotFoundException623{624SerialCallbackContext ctx = curContext;625if (ctx == null) {626throw new NotActiveException("not in call to readObject");627}628Object curObj = ctx.getObj();629ObjectStreamClass curDesc = ctx.getDesc();630bin.setBlockDataMode(false);631defaultReadFields(curObj, curDesc);632bin.setBlockDataMode(true);633if (!curDesc.hasWriteObjectData()) {634/*635* Fix for 4360508: since stream does not contain terminating636* TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere637* knows to simulate end-of-custom-data behavior.638*/639defaultDataEnd = true;640}641ClassNotFoundException ex = handles.lookupException(passHandle);642if (ex != null) {643throw ex;644}645}646647/**648* Reads the persistent fields from the stream and makes them available by649* name.650*651* @return the <code>GetField</code> object representing the persistent652* fields of the object being deserialized653* @throws ClassNotFoundException if the class of a serialized object654* could not be found.655* @throws IOException if an I/O error occurs.656* @throws NotActiveException if the stream is not currently reading657* objects.658* @since 1.2659*/660public ObjectInputStream.GetField readFields()661throws IOException, ClassNotFoundException662{663SerialCallbackContext ctx = curContext;664if (ctx == null) {665throw new NotActiveException("not in call to readObject");666}667Object curObj = ctx.getObj();668ObjectStreamClass curDesc = ctx.getDesc();669bin.setBlockDataMode(false);670GetFieldImpl getField = new GetFieldImpl(curDesc);671getField.readFields();672bin.setBlockDataMode(true);673if (!curDesc.hasWriteObjectData()) {674/*675* Fix for 4360508: since stream does not contain terminating676* TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere677* knows to simulate end-of-custom-data behavior.678*/679defaultDataEnd = true;680}681682return getField;683}684685/**686* Register an object to be validated before the graph is returned. While687* similar to resolveObject these validations are called after the entire688* graph has been reconstituted. Typically, a readObject method will689* register the object with the stream so that when all of the objects are690* restored a final set of validations can be performed.691*692* @param obj the object to receive the validation callback.693* @param prio controls the order of callbacks;zero is a good default.694* Use higher numbers to be called back earlier, lower numbers for695* later callbacks. Within a priority, callbacks are processed in696* no particular order.697* @throws NotActiveException The stream is not currently reading objects698* so it is invalid to register a callback.699* @throws InvalidObjectException The validation object is null.700*/701public void registerValidation(ObjectInputValidation obj, int prio)702throws NotActiveException, InvalidObjectException703{704if (depth == 0) {705throw new NotActiveException("stream inactive");706}707vlist.register(obj, prio);708}709710/**711* Load the local class equivalent of the specified stream class712* description. Subclasses may implement this method to allow classes to713* be fetched from an alternate source.714*715* <p>The corresponding method in <code>ObjectOutputStream</code> is716* <code>annotateClass</code>. This method will be invoked only once for717* each unique class in the stream. This method can be implemented by718* subclasses to use an alternate loading mechanism but must return a719* <code>Class</code> object. Once returned, if the class is not an array720* class, its serialVersionUID is compared to the serialVersionUID of the721* serialized class, and if there is a mismatch, the deserialization fails722* and an {@link InvalidClassException} is thrown.723*724* <p>The default implementation of this method in725* <code>ObjectInputStream</code> returns the result of calling726* <pre>727* Class.forName(desc.getName(), false, loader)728* </pre>729* where <code>loader</code> is determined as follows: if there is a730* method on the current thread's stack whose declaring class was731* defined by a user-defined class loader (and was not a generated to732* implement reflective invocations), then <code>loader</code> is class733* loader corresponding to the closest such method to the currently734* executing frame; otherwise, <code>loader</code> is735* <code>null</code>. If this call results in a736* <code>ClassNotFoundException</code> and the name of the passed737* <code>ObjectStreamClass</code> instance is the Java language keyword738* for a primitive type or void, then the <code>Class</code> object739* representing that primitive type or void will be returned740* (e.g., an <code>ObjectStreamClass</code> with the name741* <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).742* Otherwise, the <code>ClassNotFoundException</code> will be thrown to743* the caller of this method.744*745* @param desc an instance of class <code>ObjectStreamClass</code>746* @return a <code>Class</code> object corresponding to <code>desc</code>747* @throws IOException any of the usual Input/Output exceptions.748* @throws ClassNotFoundException if class of a serialized object cannot749* be found.750*/751protected Class<?> resolveClass(ObjectStreamClass desc)752throws IOException, ClassNotFoundException753{754String name = desc.getName();755try {756return Class.forName(name, false, latestUserDefinedLoader());757} catch (ClassNotFoundException ex) {758Class<?> cl = primClasses.get(name);759if (cl != null) {760return cl;761} else {762throw ex;763}764}765}766767/**768* Returns a proxy class that implements the interfaces named in a proxy769* class descriptor; subclasses may implement this method to read custom770* data from the stream along with the descriptors for dynamic proxy771* classes, allowing them to use an alternate loading mechanism for the772* interfaces and the proxy class.773*774* <p>This method is called exactly once for each unique proxy class775* descriptor in the stream.776*777* <p>The corresponding method in <code>ObjectOutputStream</code> is778* <code>annotateProxyClass</code>. For a given subclass of779* <code>ObjectInputStream</code> that overrides this method, the780* <code>annotateProxyClass</code> method in the corresponding subclass of781* <code>ObjectOutputStream</code> must write any data or objects read by782* this method.783*784* <p>The default implementation of this method in785* <code>ObjectInputStream</code> returns the result of calling786* <code>Proxy.getProxyClass</code> with the list of <code>Class</code>787* objects for the interfaces that are named in the <code>interfaces</code>788* parameter. The <code>Class</code> object for each interface name789* <code>i</code> is the value returned by calling790* <pre>791* Class.forName(i, false, loader)792* </pre>793* where <code>loader</code> is that of the first non-<code>null</code>794* class loader up the execution stack, or <code>null</code> if no795* non-<code>null</code> class loaders are on the stack (the same class796* loader choice used by the <code>resolveClass</code> method). Unless any797* of the resolved interfaces are non-public, this same value of798* <code>loader</code> is also the class loader passed to799* <code>Proxy.getProxyClass</code>; if non-public interfaces are present,800* their class loader is passed instead (if more than one non-public801* interface class loader is encountered, an802* <code>IllegalAccessError</code> is thrown).803* If <code>Proxy.getProxyClass</code> throws an804* <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>805* will throw a <code>ClassNotFoundException</code> containing the806* <code>IllegalArgumentException</code>.807*808* @param interfaces the list of interface names that were809* deserialized in the proxy class descriptor810* @return a proxy class for the specified interfaces811* @throws IOException any exception thrown by the underlying812* <code>InputStream</code>813* @throws ClassNotFoundException if the proxy class or any of the814* named interfaces could not be found815* @see ObjectOutputStream#annotateProxyClass(Class)816* @since 1.3817*/818protected Class<?> resolveProxyClass(String[] interfaces)819throws IOException, ClassNotFoundException820{821ClassLoader latestLoader = latestUserDefinedLoader();822ClassLoader nonPublicLoader = null;823boolean hasNonPublicInterface = false;824825// define proxy in class loader of non-public interface(s), if any826Class<?>[] classObjs = new Class<?>[interfaces.length];827for (int i = 0; i < interfaces.length; i++) {828Class<?> cl = Class.forName(interfaces[i], false, latestLoader);829if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {830if (hasNonPublicInterface) {831if (nonPublicLoader != cl.getClassLoader()) {832throw new IllegalAccessError(833"conflicting non-public interface class loaders");834}835} else {836nonPublicLoader = cl.getClassLoader();837hasNonPublicInterface = true;838}839}840classObjs[i] = cl;841}842try {843return Proxy.getProxyClass(844hasNonPublicInterface ? nonPublicLoader : latestLoader,845classObjs);846} catch (IllegalArgumentException e) {847throw new ClassNotFoundException(null, e);848}849}850851/**852* This method will allow trusted subclasses of ObjectInputStream to853* substitute one object for another during deserialization. Replacing854* objects is disabled until enableResolveObject is called. The855* enableResolveObject method checks that the stream requesting to resolve856* object can be trusted. Every reference to serializable objects is passed857* to resolveObject. To insure that the private state of objects is not858* unintentionally exposed only trusted streams may use resolveObject.859*860* <p>This method is called after an object has been read but before it is861* returned from readObject. The default resolveObject method just returns862* the same object.863*864* <p>When a subclass is replacing objects it must insure that the865* substituted object is compatible with every field where the reference866* will be stored. Objects whose type is not a subclass of the type of the867* field or array element abort the serialization by raising an exception868* and the object is not be stored.869*870* <p>This method is called only once when each object is first871* encountered. All subsequent references to the object will be redirected872* to the new object.873*874* @param obj object to be substituted875* @return the substituted object876* @throws IOException Any of the usual Input/Output exceptions.877*/878protected Object resolveObject(Object obj) throws IOException {879return obj;880}881882/**883* Enable the stream to allow objects read from the stream to be replaced.884* When enabled, the resolveObject method is called for every object being885* deserialized.886*887* <p>If <i>enable</i> is true, and there is a security manager installed,888* this method first calls the security manager's889* <code>checkPermission</code> method with the890* <code>SerializablePermission("enableSubstitution")</code> permission to891* ensure it's ok to enable the stream to allow objects read from the892* stream to be replaced.893*894* @param enable true for enabling use of <code>resolveObject</code> for895* every object being deserialized896* @return the previous setting before this method was invoked897* @throws SecurityException if a security manager exists and its898* <code>checkPermission</code> method denies enabling the stream899* to allow objects read from the stream to be replaced.900* @see SecurityManager#checkPermission901* @see java.io.SerializablePermission902*/903protected boolean enableResolveObject(boolean enable)904throws SecurityException905{906if (enable == enableResolve) {907return enable;908}909if (enable) {910SecurityManager sm = System.getSecurityManager();911if (sm != null) {912sm.checkPermission(SUBSTITUTION_PERMISSION);913}914}915enableResolve = enable;916return !enableResolve;917}918919/**920* The readStreamHeader method is provided to allow subclasses to read and921* verify their own stream headers. It reads and verifies the magic number922* and version number.923*924* @throws IOException if there are I/O errors while reading from the925* underlying <code>InputStream</code>926* @throws StreamCorruptedException if control information in the stream927* is inconsistent928*/929protected void readStreamHeader()930throws IOException, StreamCorruptedException931{932short s0 = bin.readShort();933short s1 = bin.readShort();934if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {935throw new StreamCorruptedException(936String.format("invalid stream header: %04X%04X", s0, s1));937}938}939940/**941* Read a class descriptor from the serialization stream. This method is942* called when the ObjectInputStream expects a class descriptor as the next943* item in the serialization stream. Subclasses of ObjectInputStream may944* override this method to read in class descriptors that have been written945* in non-standard formats (by subclasses of ObjectOutputStream which have946* overridden the <code>writeClassDescriptor</code> method). By default,947* this method reads class descriptors according to the format defined in948* the Object Serialization specification.949*950* @return the class descriptor read951* @throws IOException If an I/O error has occurred.952* @throws ClassNotFoundException If the Class of a serialized object used953* in the class descriptor representation cannot be found954* @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)955* @since 1.3956*/957protected ObjectStreamClass readClassDescriptor()958throws IOException, ClassNotFoundException959{960ObjectStreamClass desc = new ObjectStreamClass();961desc.readNonProxy(this);962return desc;963}964965/**966* Reads a byte of data. This method will block if no input is available.967*968* @return the byte read, or -1 if the end of the stream is reached.969* @throws IOException If an I/O error has occurred.970*/971public int read() throws IOException {972return bin.read();973}974975/**976* Reads into an array of bytes. This method will block until some input977* is available. Consider using java.io.DataInputStream.readFully to read978* exactly 'length' bytes.979*980* @param buf the buffer into which the data is read981* @param off the start offset of the data982* @param len the maximum number of bytes read983* @return the actual number of bytes read, -1 is returned when the end of984* the stream is reached.985* @throws IOException If an I/O error has occurred.986* @see java.io.DataInputStream#readFully(byte[],int,int)987*/988public int read(byte[] buf, int off, int len) throws IOException {989if (buf == null) {990throw new NullPointerException();991}992int endoff = off + len;993if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {994throw new IndexOutOfBoundsException();995}996return bin.read(buf, off, len, false);997}998999/**1000* Returns the number of bytes that can be read without blocking.1001*1002* @return the number of available bytes.1003* @throws IOException if there are I/O errors while reading from the1004* underlying <code>InputStream</code>1005*/1006public int available() throws IOException {1007return bin.available();1008}10091010/**1011* Closes the input stream. Must be called to release any resources1012* associated with the stream.1013*1014* @throws IOException If an I/O error has occurred.1015*/1016public void close() throws IOException {1017/*1018* Even if stream already closed, propagate redundant close to1019* underlying stream to stay consistent with previous implementations.1020*/1021closed = true;1022if (depth == 0) {1023clear();1024}1025bin.close();1026}10271028/**1029* Reads in a boolean.1030*1031* @return the boolean read.1032* @throws EOFException If end of file is reached.1033* @throws IOException If other I/O error has occurred.1034*/1035public boolean readBoolean() throws IOException {1036return bin.readBoolean();1037}10381039/**1040* Reads an 8 bit byte.1041*1042* @return the 8 bit byte read.1043* @throws EOFException If end of file is reached.1044* @throws IOException If other I/O error has occurred.1045*/1046public byte readByte() throws IOException {1047return bin.readByte();1048}10491050/**1051* Reads an unsigned 8 bit byte.1052*1053* @return the 8 bit byte read.1054* @throws EOFException If end of file is reached.1055* @throws IOException If other I/O error has occurred.1056*/1057public int readUnsignedByte() throws IOException {1058return bin.readUnsignedByte();1059}10601061/**1062* Reads a 16 bit char.1063*1064* @return the 16 bit char read.1065* @throws EOFException If end of file is reached.1066* @throws IOException If other I/O error has occurred.1067*/1068public char readChar() throws IOException {1069return bin.readChar();1070}10711072/**1073* Reads a 16 bit short.1074*1075* @return the 16 bit short read.1076* @throws EOFException If end of file is reached.1077* @throws IOException If other I/O error has occurred.1078*/1079public short readShort() throws IOException {1080return bin.readShort();1081}10821083/**1084* Reads an unsigned 16 bit short.1085*1086* @return the 16 bit short read.1087* @throws EOFException If end of file is reached.1088* @throws IOException If other I/O error has occurred.1089*/1090public int readUnsignedShort() throws IOException {1091return bin.readUnsignedShort();1092}10931094/**1095* Reads a 32 bit int.1096*1097* @return the 32 bit integer read.1098* @throws EOFException If end of file is reached.1099* @throws IOException If other I/O error has occurred.1100*/1101public int readInt() throws IOException {1102return bin.readInt();1103}11041105/**1106* Reads a 64 bit long.1107*1108* @return the read 64 bit long.1109* @throws EOFException If end of file is reached.1110* @throws IOException If other I/O error has occurred.1111*/1112public long readLong() throws IOException {1113return bin.readLong();1114}11151116/**1117* Reads a 32 bit float.1118*1119* @return the 32 bit float read.1120* @throws EOFException If end of file is reached.1121* @throws IOException If other I/O error has occurred.1122*/1123public float readFloat() throws IOException {1124return bin.readFloat();1125}11261127/**1128* Reads a 64 bit double.1129*1130* @return the 64 bit double read.1131* @throws EOFException If end of file is reached.1132* @throws IOException If other I/O error has occurred.1133*/1134public double readDouble() throws IOException {1135return bin.readDouble();1136}11371138/**1139* Reads bytes, blocking until all bytes are read.1140*1141* @param buf the buffer into which the data is read1142* @throws EOFException If end of file is reached.1143* @throws IOException If other I/O error has occurred.1144*/1145public void readFully(byte[] buf) throws IOException {1146bin.readFully(buf, 0, buf.length, false);1147}11481149/**1150* Reads bytes, blocking until all bytes are read.1151*1152* @param buf the buffer into which the data is read1153* @param off the start offset of the data1154* @param len the maximum number of bytes to read1155* @throws EOFException If end of file is reached.1156* @throws IOException If other I/O error has occurred.1157*/1158public void readFully(byte[] buf, int off, int len) throws IOException {1159int endoff = off + len;1160if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {1161throw new IndexOutOfBoundsException();1162}1163bin.readFully(buf, off, len, false);1164}11651166/**1167* Skips bytes.1168*1169* @param len the number of bytes to be skipped1170* @return the actual number of bytes skipped.1171* @throws IOException If an I/O error has occurred.1172*/1173public int skipBytes(int len) throws IOException {1174return bin.skipBytes(len);1175}11761177/**1178* Reads in a line that has been terminated by a \n, \r, \r\n or EOF.1179*1180* @return a String copy of the line.1181* @throws IOException if there are I/O errors while reading from the1182* underlying <code>InputStream</code>1183* @deprecated This method does not properly convert bytes to characters.1184* see DataInputStream for the details and alternatives.1185*/1186@Deprecated1187public String readLine() throws IOException {1188return bin.readLine();1189}11901191/**1192* Reads a String in1193* <a href="DataInput.html#modified-utf-8">modified UTF-8</a>1194* format.1195*1196* @return the String.1197* @throws IOException if there are I/O errors while reading from the1198* underlying <code>InputStream</code>1199* @throws UTFDataFormatException if read bytes do not represent a valid1200* modified UTF-8 encoding of a string1201*/1202public String readUTF() throws IOException {1203return bin.readUTF();1204}12051206/**1207* Returns the serialization filter for this stream.1208* The serialization filter is the most recent filter set in1209* {@link #setInternalObjectInputFilter setInternalObjectInputFilter} or1210* the initial process-wide filter from1211* {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}.1212*1213* @return the serialization filter for the stream; may be null1214*/1215private final ObjectInputFilter getInternalObjectInputFilter() {1216return serialFilter;1217}12181219/**1220* Set the serialization filter for the stream.1221* The filter's {@link ObjectInputFilter#checkInput checkInput} method is called1222* for each class and reference in the stream.1223* The filter can check any or all of the class, the array length, the number1224* of references, the depth of the graph, and the size of the input stream.1225* <p>1226* If the filter returns {@link ObjectInputFilter.Status#REJECTED Status.REJECTED},1227* {@code null} or throws a {@link RuntimeException},1228* the active {@code readObject} or {@code readUnshared}1229* throws {@link InvalidClassException}, otherwise deserialization1230* continues uninterrupted.1231* <p>1232* The serialization filter is initialized to the value of1233* {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}1234* when the {@code ObjectInputStream} is constructed and can be set1235* to a custom filter only once.1236*1237* @implSpec1238* The filter, when not {@code null}, is invoked during {@link #readObject readObject}1239* and {@link #readUnshared readUnshared} for each object1240* (regular or class) in the stream including the following:1241* <ul>1242* <li>each object reference previously deserialized from the stream1243* (class is {@code null}, arrayLength is -1),1244* <li>each regular class (class is not {@code null}, arrayLength is -1),1245* <li>each interface of a dynamic proxy and the dynamic proxy class itself1246* (class is not {@code null}, arrayLength is -1),1247* <li>each array is filtered using the array type and length of the array1248* (class is the array type, arrayLength is the requested length),1249* <li>each object replaced by its class' {@code readResolve} method1250* is filtered using the replacement object's class, if not {@code null},1251* and if it is an array, the arrayLength, otherwise -1,1252* <li>and each object replaced by {@link #resolveObject resolveObject}1253* is filtered using the replacement object's class, if not {@code null},1254* and if it is an array, the arrayLength, otherwise -1.1255* </ul>1256*1257* When the {@link ObjectInputFilter#checkInput checkInput} method is invoked1258* it is given access to the current class, the array length,1259* the current number of references already read from the stream,1260* the depth of nested calls to {@link #readObject readObject} or1261* {@link #readUnshared readUnshared},1262* and the implementation dependent number of bytes consumed from the input stream.1263* <p>1264* Each call to {@link #readObject readObject} or1265* {@link #readUnshared readUnshared} increases the depth by 11266* before reading an object and decreases by 1 before returning1267* normally or exceptionally.1268* The depth starts at {@code 1} and increases for each nested object and1269* decrements when each nested call returns.1270* The count of references in the stream starts at {@code 1} and1271* is increased before reading an object.1272*1273* @param filter the filter, may be null1274* @throws SecurityException if there is security manager and the1275* {@code SerializablePermission("serialFilter")} is not granted1276* @throws IllegalStateException if the {@linkplain #getInternalObjectInputFilter() current filter}1277* is not {@code null} and is not the process-wide filter1278*/1279private final void setInternalObjectInputFilter(ObjectInputFilter filter) {1280SecurityManager sm = System.getSecurityManager();1281if (sm != null) {1282sm.checkPermission(new SerializablePermission("serialFilter"));1283}1284// Allow replacement of the process-wide filter if not already set1285if (serialFilter != null &&1286serialFilter != ObjectInputFilter.Config.getSerialFilter()) {1287throw new IllegalStateException("filter can not be set more than once");1288}1289if (totalObjectRefs > 0 && !Caches.SET_FILTER_AFTER_READ) {1290throw new IllegalStateException(1291"filter can not be set after an object has been read");1292}1293this.serialFilter = filter;1294}12951296/**1297* Invoke the serialization filter if non-null.1298* If the filter rejects or an exception is thrown, throws InvalidClassException.1299*1300* @param clazz the class; may be null1301* @param arrayLength the array length requested; use {@code -1} if not creating an array1302* @throws InvalidClassException if it rejected by the filter or1303* a {@link RuntimeException} is thrown1304*/1305private void filterCheck(Class<?> clazz, int arrayLength)1306throws InvalidClassException {1307if (serialFilter != null) {1308RuntimeException ex = null;1309ObjectInputFilter.Status status;1310// Info about the stream is not available if overridden by subclass, return 01311long bytesRead = (bin == null) ? 0 : bin.getBytesRead();1312try {1313status = serialFilter.checkInput(new FilterValues(clazz, arrayLength,1314totalObjectRefs, depth, bytesRead));1315} catch (RuntimeException e) {1316// Preventive interception of an exception to log1317status = ObjectInputFilter.Status.REJECTED;1318ex = e;1319}1320if (status == null ||1321status == ObjectInputFilter.Status.REJECTED) {1322// Debug logging of filter checks that fail1323if (Logging.infoLogger != null) {1324Logging.infoLogger.info(1325"ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",1326status, clazz, arrayLength, totalObjectRefs, depth, bytesRead,1327Objects.toString(ex, "n/a"));1328}1329InvalidClassException ice = new InvalidClassException("filter status: " + status);1330ice.initCause(ex);1331throw ice;1332} else {1333// Trace logging for those that succeed1334if (Logging.traceLogger != null) {1335Logging.traceLogger.finer(1336"ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",1337status, clazz, arrayLength, totalObjectRefs, depth, bytesRead,1338Objects.toString(ex, "n/a"));1339}1340}1341}1342}13431344/**1345* Checks the given array type and length to ensure that creation of such1346* an array is permitted by this ObjectInputStream. The arrayType argument1347* must represent an actual array type.1348*1349* This private method is called via SharedSecrets.1350*1351* @param arrayType the array type1352* @param arrayLength the array length1353* @throws NullPointerException if arrayType is null1354* @throws IllegalArgumentException if arrayType isn't actually an array type1355* @throws NegativeArraySizeException if arrayLength is negative1356* @throws InvalidClassException if the filter rejects creation1357*/1358private void checkArray(Class<?> arrayType, int arrayLength) throws InvalidClassException {1359Objects.requireNonNull(arrayType);1360if (! arrayType.isArray()) {1361throw new IllegalArgumentException("not an array type");1362}13631364if (arrayLength < 0) {1365throw new NegativeArraySizeException();1366}13671368filterCheck(arrayType, arrayLength);1369}13701371/**1372* Provide access to the persistent fields read from the input stream.1373*/1374public static abstract class GetField {13751376/**1377* Get the ObjectStreamClass that describes the fields in the stream.1378*1379* @return the descriptor class that describes the serializable fields1380*/1381public abstract ObjectStreamClass getObjectStreamClass();13821383/**1384* Return true if the named field is defaulted and has no value in this1385* stream.1386*1387* @param name the name of the field1388* @return true, if and only if the named field is defaulted1389* @throws IOException if there are I/O errors while reading from1390* the underlying <code>InputStream</code>1391* @throws IllegalArgumentException if <code>name</code> does not1392* correspond to a serializable field1393*/1394public abstract boolean defaulted(String name) throws IOException;13951396/**1397* Get the value of the named boolean field from the persistent field.1398*1399* @param name the name of the field1400* @param val the default value to use if <code>name</code> does not1401* have a value1402* @return the value of the named <code>boolean</code> field1403* @throws IOException if there are I/O errors while reading from the1404* underlying <code>InputStream</code>1405* @throws IllegalArgumentException if type of <code>name</code> is1406* not serializable or if the field type is incorrect1407*/1408public abstract boolean get(String name, boolean val)1409throws IOException;14101411/**1412* Get the value of the named byte field from the persistent field.1413*1414* @param name the name of the field1415* @param val the default value to use if <code>name</code> does not1416* have a value1417* @return the value of the named <code>byte</code> field1418* @throws IOException if there are I/O errors while reading from the1419* underlying <code>InputStream</code>1420* @throws IllegalArgumentException if type of <code>name</code> is1421* not serializable or if the field type is incorrect1422*/1423public abstract byte get(String name, byte val) throws IOException;14241425/**1426* Get the value of the named char field from the persistent field.1427*1428* @param name the name of the field1429* @param val the default value to use if <code>name</code> does not1430* have a value1431* @return the value of the named <code>char</code> field1432* @throws IOException if there are I/O errors while reading from the1433* underlying <code>InputStream</code>1434* @throws IllegalArgumentException if type of <code>name</code> is1435* not serializable or if the field type is incorrect1436*/1437public abstract char get(String name, char val) throws IOException;14381439/**1440* Get the value of the named short field from the persistent field.1441*1442* @param name the name of the field1443* @param val the default value to use if <code>name</code> does not1444* have a value1445* @return the value of the named <code>short</code> field1446* @throws IOException if there are I/O errors while reading from the1447* underlying <code>InputStream</code>1448* @throws IllegalArgumentException if type of <code>name</code> is1449* not serializable or if the field type is incorrect1450*/1451public abstract short get(String name, short val) throws IOException;14521453/**1454* Get the value of the named int field from the persistent field.1455*1456* @param name the name of the field1457* @param val the default value to use if <code>name</code> does not1458* have a value1459* @return the value of the named <code>int</code> field1460* @throws IOException if there are I/O errors while reading from the1461* underlying <code>InputStream</code>1462* @throws IllegalArgumentException if type of <code>name</code> is1463* not serializable or if the field type is incorrect1464*/1465public abstract int get(String name, int val) throws IOException;14661467/**1468* Get the value of the named long field from the persistent field.1469*1470* @param name the name of the field1471* @param val the default value to use if <code>name</code> does not1472* have a value1473* @return the value of the named <code>long</code> field1474* @throws IOException if there are I/O errors while reading from the1475* underlying <code>InputStream</code>1476* @throws IllegalArgumentException if type of <code>name</code> is1477* not serializable or if the field type is incorrect1478*/1479public abstract long get(String name, long val) throws IOException;14801481/**1482* Get the value of the named float field from the persistent field.1483*1484* @param name the name of the field1485* @param val the default value to use if <code>name</code> does not1486* have a value1487* @return the value of the named <code>float</code> field1488* @throws IOException if there are I/O errors while reading from the1489* underlying <code>InputStream</code>1490* @throws IllegalArgumentException if type of <code>name</code> is1491* not serializable or if the field type is incorrect1492*/1493public abstract float get(String name, float val) throws IOException;14941495/**1496* Get the value of the named double field from the persistent field.1497*1498* @param name the name of the field1499* @param val the default value to use if <code>name</code> does not1500* have a value1501* @return the value of the named <code>double</code> field1502* @throws IOException if there are I/O errors while reading from the1503* underlying <code>InputStream</code>1504* @throws IllegalArgumentException if type of <code>name</code> is1505* not serializable or if the field type is incorrect1506*/1507public abstract double get(String name, double val) throws IOException;15081509/**1510* Get the value of the named Object field from the persistent field.1511*1512* @param name the name of the field1513* @param val the default value to use if <code>name</code> does not1514* have a value1515* @return the value of the named <code>Object</code> field1516* @throws IOException if there are I/O errors while reading from the1517* underlying <code>InputStream</code>1518* @throws IllegalArgumentException if type of <code>name</code> is1519* not serializable or if the field type is incorrect1520*/1521public abstract Object get(String name, Object val) throws IOException;1522}15231524/**1525* Verifies that this (possibly subclass) instance can be constructed1526* without violating security constraints: the subclass must not override1527* security-sensitive non-final methods, or else the1528* "enableSubclassImplementation" SerializablePermission is checked.1529*/1530private void verifySubclass() {1531Class<?> cl = getClass();1532if (cl == ObjectInputStream.class) {1533return;1534}1535SecurityManager sm = System.getSecurityManager();1536if (sm == null) {1537return;1538}1539processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);1540WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);1541Boolean result = Caches.subclassAudits.get(key);1542if (result == null) {1543result = Boolean.valueOf(auditSubclass(cl));1544Caches.subclassAudits.putIfAbsent(key, result);1545}1546if (result.booleanValue()) {1547return;1548}1549sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);1550}15511552/**1553* Performs reflective checks on given subclass to verify that it doesn't1554* override security-sensitive non-final methods. Returns true if subclass1555* is "safe", false otherwise.1556*/1557private static boolean auditSubclass(final Class<?> subcl) {1558Boolean result = AccessController.doPrivileged(1559new PrivilegedAction<Boolean>() {1560public Boolean run() {1561for (Class<?> cl = subcl;1562cl != ObjectInputStream.class;1563cl = cl.getSuperclass())1564{1565try {1566cl.getDeclaredMethod(1567"readUnshared", (Class[]) null);1568return Boolean.FALSE;1569} catch (NoSuchMethodException ex) {1570}1571try {1572cl.getDeclaredMethod("readFields", (Class[]) null);1573return Boolean.FALSE;1574} catch (NoSuchMethodException ex) {1575}1576}1577return Boolean.TRUE;1578}1579}1580);1581return result.booleanValue();1582}15831584/**1585* Clears internal data structures.1586*/1587private void clear() {1588handles.clear();1589vlist.clear();1590}15911592/**1593* Underlying readObject implementation.1594* @param type a type expected to be deserialized; non-null1595* @param unshared true if the object can not be a reference to a shared object, otherwise false1596*/1597private Object readObject0(Class<?> type, boolean unshared) throws IOException {1598boolean oldMode = bin.getBlockDataMode();1599if (oldMode) {1600int remain = bin.currentBlockRemaining();1601if (remain > 0) {1602throw new OptionalDataException(remain);1603} else if (defaultDataEnd) {1604/*1605* Fix for 4360508: stream is currently at the end of a field1606* value block written via default serialization; since there1607* is no terminating TC_ENDBLOCKDATA tag, simulate1608* end-of-custom-data behavior explicitly.1609*/1610throw new OptionalDataException(true);1611}1612bin.setBlockDataMode(false);1613}16141615byte tc;1616while ((tc = bin.peekByte()) == TC_RESET) {1617bin.readByte();1618handleReset();1619}16201621depth++;1622totalObjectRefs++;1623try {1624switch (tc) {1625case TC_NULL:1626return readNull();16271628case TC_REFERENCE:1629// check the type of the existing object1630return type.cast(readHandle(unshared));16311632case TC_CLASS:1633if (type == String.class) {1634throw new ClassCastException("Cannot cast a class to java.lang.String");1635}1636return readClass(unshared);16371638case TC_CLASSDESC:1639case TC_PROXYCLASSDESC:1640if (type == String.class) {1641throw new ClassCastException("Cannot cast a class to java.lang.String");1642}1643return readClassDesc(unshared);16441645case TC_STRING:1646case TC_LONGSTRING:1647return checkResolve(readString(unshared));16481649case TC_ARRAY:1650if (type == String.class) {1651throw new ClassCastException("Cannot cast an array to java.lang.String");1652}1653return checkResolve(readArray(unshared));16541655case TC_ENUM:1656if (type == String.class) {1657throw new ClassCastException("Cannot cast an enum to java.lang.String");1658}1659return checkResolve(readEnum(unshared));16601661case TC_OBJECT:1662if (type == String.class) {1663throw new ClassCastException("Cannot cast an object to java.lang.String");1664}1665return checkResolve(readOrdinaryObject(unshared));16661667case TC_EXCEPTION:1668if (type == String.class) {1669throw new ClassCastException("Cannot cast an exception to java.lang.String");1670}1671IOException ex = readFatalException();1672throw new WriteAbortedException("writing aborted", ex);16731674case TC_BLOCKDATA:1675case TC_BLOCKDATALONG:1676if (oldMode) {1677bin.setBlockDataMode(true);1678bin.peek(); // force header read1679throw new OptionalDataException(1680bin.currentBlockRemaining());1681} else {1682throw new StreamCorruptedException(1683"unexpected block data");1684}16851686case TC_ENDBLOCKDATA:1687if (oldMode) {1688throw new OptionalDataException(true);1689} else {1690throw new StreamCorruptedException(1691"unexpected end of block data");1692}16931694default:1695throw new StreamCorruptedException(1696String.format("invalid type code: %02X", tc));1697}1698} finally {1699depth--;1700bin.setBlockDataMode(oldMode);1701}1702}17031704/**1705* If resolveObject has been enabled and given object does not have an1706* exception associated with it, calls resolveObject to determine1707* replacement for object, and updates handle table accordingly. Returns1708* replacement object, or echoes provided object if no replacement1709* occurred. Expects that passHandle is set to given object's handle prior1710* to calling this method.1711*/1712private Object checkResolve(Object obj) throws IOException {1713if (!enableResolve || handles.lookupException(passHandle) != null) {1714return obj;1715}1716Object rep = resolveObject(obj);1717if (rep != obj) {1718// The type of the original object has been filtered but resolveObject1719// may have replaced it; filter the replacement's type1720if (rep != null) {1721if (rep.getClass().isArray()) {1722filterCheck(rep.getClass(), Array.getLength(rep));1723} else {1724filterCheck(rep.getClass(), -1);1725}1726}1727handles.setObject(passHandle, rep);1728}1729return rep;1730}17311732/**1733* Reads string without allowing it to be replaced in stream. Called from1734* within ObjectStreamClass.read().1735*/1736String readTypeString() throws IOException {1737int oldHandle = passHandle;1738try {1739byte tc = bin.peekByte();1740switch (tc) {1741case TC_NULL:1742return (String) readNull();17431744case TC_REFERENCE:1745return (String) readHandle(false);17461747case TC_STRING:1748case TC_LONGSTRING:1749return readString(false);17501751default:1752throw new StreamCorruptedException(1753String.format("invalid type code: %02X", tc));1754}1755} finally {1756passHandle = oldHandle;1757}1758}17591760/**1761* Reads in null code, sets passHandle to NULL_HANDLE and returns null.1762*/1763private Object readNull() throws IOException {1764if (bin.readByte() != TC_NULL) {1765throw new InternalError();1766}1767passHandle = NULL_HANDLE;1768return null;1769}17701771/**1772* Reads in object handle, sets passHandle to the read handle, and returns1773* object associated with the handle.1774*/1775private Object readHandle(boolean unshared) throws IOException {1776if (bin.readByte() != TC_REFERENCE) {1777throw new InternalError();1778}1779passHandle = bin.readInt() - baseWireHandle;1780if (passHandle < 0 || passHandle >= handles.size()) {1781throw new StreamCorruptedException(1782String.format("invalid handle value: %08X", passHandle +1783baseWireHandle));1784}1785if (unshared) {1786// REMIND: what type of exception to throw here?1787throw new InvalidObjectException(1788"cannot read back reference as unshared");1789}17901791Object obj = handles.lookupObject(passHandle);1792if (obj == unsharedMarker) {1793// REMIND: what type of exception to throw here?1794throw new InvalidObjectException(1795"cannot read back reference to unshared object");1796}1797filterCheck(null, -1); // just a check for number of references, depth, no class1798return obj;1799}18001801/**1802* Reads in and returns class object. Sets passHandle to class object's1803* assigned handle. Returns null if class is unresolvable (in which case a1804* ClassNotFoundException will be associated with the class' handle in the1805* handle table).1806*/1807private Class<?> readClass(boolean unshared) throws IOException {1808if (bin.readByte() != TC_CLASS) {1809throw new InternalError();1810}1811ObjectStreamClass desc = readClassDesc(false);1812Class<?> cl = desc.forClass();1813passHandle = handles.assign(unshared ? unsharedMarker : cl);18141815ClassNotFoundException resolveEx = desc.getResolveException();1816if (resolveEx != null) {1817handles.markException(passHandle, resolveEx);1818}18191820handles.finish(passHandle);1821return cl;1822}18231824/**1825* Reads in and returns (possibly null) class descriptor. Sets passHandle1826* to class descriptor's assigned handle. If class descriptor cannot be1827* resolved to a class in the local VM, a ClassNotFoundException is1828* associated with the class descriptor's handle.1829*/1830private ObjectStreamClass readClassDesc(boolean unshared)1831throws IOException1832{1833byte tc = bin.peekByte();1834ObjectStreamClass descriptor;1835switch (tc) {1836case TC_NULL:1837descriptor = (ObjectStreamClass) readNull();1838break;1839case TC_REFERENCE:1840descriptor = (ObjectStreamClass) readHandle(unshared);1841// Should only reference initialized class descriptors1842descriptor.checkInitialized();1843break;1844case TC_PROXYCLASSDESC:1845descriptor = readProxyDesc(unshared);1846break;1847case TC_CLASSDESC:1848descriptor = readNonProxyDesc(unshared);1849break;1850default:1851throw new StreamCorruptedException(1852String.format("invalid type code: %02X", tc));1853}1854if (descriptor != null) {1855validateDescriptor(descriptor);1856}1857return descriptor;1858}18591860private boolean isCustomSubclass() {1861// Return true if this class is a custom subclass of ObjectInputStream1862return getClass().getClassLoader()1863!= ObjectInputStream.class.getClassLoader();1864}18651866/**1867* Reads in and returns class descriptor for a dynamic proxy class. Sets1868* passHandle to proxy class descriptor's assigned handle. If proxy class1869* descriptor cannot be resolved to a class in the local VM, a1870* ClassNotFoundException is associated with the descriptor's handle.1871*/1872private ObjectStreamClass readProxyDesc(boolean unshared)1873throws IOException1874{1875if (bin.readByte() != TC_PROXYCLASSDESC) {1876throw new InternalError();1877}18781879ObjectStreamClass desc = new ObjectStreamClass();1880int descHandle = handles.assign(unshared ? unsharedMarker : desc);1881passHandle = NULL_HANDLE;18821883int numIfaces = bin.readInt();1884if (numIfaces > 65535) {1885// Report specification limit exceeded1886throw new InvalidObjectException("interface limit exceeded: " +1887numIfaces +1888", limit: " + Caches.PROXY_INTERFACE_LIMIT);1889}1890String[] ifaces = new String[numIfaces];1891for (int i = 0; i < numIfaces; i++) {1892ifaces[i] = bin.readUTF();1893}18941895// Recheck against implementation limit and throw with interface names1896if (numIfaces > Caches.PROXY_INTERFACE_LIMIT) {1897throw new InvalidObjectException("interface limit exceeded: " +1898numIfaces +1899", limit: " + Caches.PROXY_INTERFACE_LIMIT +1900"; " + Arrays.toString(ifaces));1901}1902Class<?> cl = null;1903ClassNotFoundException resolveEx = null;1904bin.setBlockDataMode(true);1905try {1906if ((cl = resolveProxyClass(ifaces)) == null) {1907resolveEx = new ClassNotFoundException("null class");1908} else if (!Proxy.isProxyClass(cl)) {1909throw new InvalidClassException("Not a proxy");1910} else {1911// ReflectUtil.checkProxyPackageAccess makes a test1912// equivalent to isCustomSubclass so there's no need1913// to condition this call to isCustomSubclass == true here.1914ReflectUtil.checkProxyPackageAccess(1915getClass().getClassLoader(),1916cl.getInterfaces());1917// Filter the interfaces1918for (Class<?> clazz : cl.getInterfaces()) {1919filterCheck(clazz, -1);1920}1921}1922} catch (ClassNotFoundException ex) {1923resolveEx = ex;1924} catch (OutOfMemoryError memerr) {1925IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " +1926Arrays.toString(ifaces));1927ex.initCause(memerr);1928throw ex;1929}19301931// Call filterCheck on the class before reading anything else1932filterCheck(cl, -1);19331934skipCustomData();19351936try {1937totalObjectRefs++;1938depth++;1939desc.initProxy(cl, resolveEx, readClassDesc(false));1940} catch (OutOfMemoryError memerr) {1941IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " +1942Arrays.toString(ifaces));1943ex.initCause(memerr);1944throw ex;1945} finally {1946depth--;1947}19481949handles.finish(descHandle);1950passHandle = descHandle;1951return desc;1952}19531954/**1955* Reads in and returns class descriptor for a class that is not a dynamic1956* proxy class. Sets passHandle to class descriptor's assigned handle. If1957* class descriptor cannot be resolved to a class in the local VM, a1958* ClassNotFoundException is associated with the descriptor's handle.1959*/1960private ObjectStreamClass readNonProxyDesc(boolean unshared)1961throws IOException1962{1963if (bin.readByte() != TC_CLASSDESC) {1964throw new InternalError();1965}19661967ObjectStreamClass desc = new ObjectStreamClass();1968int descHandle = handles.assign(unshared ? unsharedMarker : desc);1969passHandle = NULL_HANDLE;19701971ObjectStreamClass readDesc = null;1972try {1973readDesc = readClassDescriptor();1974} catch (ClassNotFoundException ex) {1975throw (IOException) new InvalidClassException(1976"failed to read class descriptor").initCause(ex);1977}19781979Class<?> cl = null;1980ClassNotFoundException resolveEx = null;1981bin.setBlockDataMode(true);1982final boolean checksRequired = isCustomSubclass();1983try {1984if ((cl = resolveClass(readDesc)) == null) {1985resolveEx = new ClassNotFoundException("null class");1986} else if (checksRequired) {1987ReflectUtil.checkPackageAccess(cl);1988}1989} catch (ClassNotFoundException ex) {1990resolveEx = ex;1991}19921993// Call filterCheck on the class before reading anything else1994filterCheck(cl, -1);19951996skipCustomData();19971998try {1999totalObjectRefs++;2000depth++;2001desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));2002} finally {2003depth--;2004}20052006handles.finish(descHandle);2007passHandle = descHandle;20082009return desc;2010}20112012/**2013* Reads in and returns new string. Sets passHandle to new string's2014* assigned handle.2015*/2016private String readString(boolean unshared) throws IOException {2017String str;2018byte tc = bin.readByte();2019switch (tc) {2020case TC_STRING:2021str = bin.readUTF();2022break;20232024case TC_LONGSTRING:2025str = bin.readLongUTF();2026break;20272028default:2029throw new StreamCorruptedException(2030String.format("invalid type code: %02X", tc));2031}2032passHandle = handles.assign(unshared ? unsharedMarker : str);2033handles.finish(passHandle);2034return str;2035}20362037/**2038* Reads in and returns array object, or null if array class is2039* unresolvable. Sets passHandle to array's assigned handle.2040*/2041private Object readArray(boolean unshared) throws IOException {2042if (bin.readByte() != TC_ARRAY) {2043throw new InternalError();2044}20452046ObjectStreamClass desc = readClassDesc(false);2047int len = bin.readInt();20482049filterCheck(desc.forClass(), len);20502051Object array = null;2052Class<?> cl, ccl = null;2053if ((cl = desc.forClass()) != null) {2054ccl = cl.getComponentType();2055array = Array.newInstance(ccl, len);2056}20572058int arrayHandle = handles.assign(unshared ? unsharedMarker : array);2059ClassNotFoundException resolveEx = desc.getResolveException();2060if (resolveEx != null) {2061handles.markException(arrayHandle, resolveEx);2062}20632064if (ccl == null) {2065for (int i = 0; i < len; i++) {2066readObject0(Object.class, false);2067}2068} else if (ccl.isPrimitive()) {2069if (ccl == Integer.TYPE) {2070bin.readInts((int[]) array, 0, len);2071} else if (ccl == Byte.TYPE) {2072bin.readFully((byte[]) array, 0, len, true);2073} else if (ccl == Long.TYPE) {2074bin.readLongs((long[]) array, 0, len);2075} else if (ccl == Float.TYPE) {2076bin.readFloats((float[]) array, 0, len);2077} else if (ccl == Double.TYPE) {2078bin.readDoubles((double[]) array, 0, len);2079} else if (ccl == Short.TYPE) {2080bin.readShorts((short[]) array, 0, len);2081} else if (ccl == Character.TYPE) {2082bin.readChars((char[]) array, 0, len);2083} else if (ccl == Boolean.TYPE) {2084bin.readBooleans((boolean[]) array, 0, len);2085} else {2086throw new InternalError();2087}2088} else {2089Object[] oa = (Object[]) array;2090for (int i = 0; i < len; i++) {2091oa[i] = readObject0(Object.class, false);2092handles.markDependency(arrayHandle, passHandle);2093}2094}20952096handles.finish(arrayHandle);2097passHandle = arrayHandle;2098return array;2099}21002101/**2102* Reads in and returns enum constant, or null if enum type is2103* unresolvable. Sets passHandle to enum constant's assigned handle.2104*/2105private Enum<?> readEnum(boolean unshared) throws IOException {2106if (bin.readByte() != TC_ENUM) {2107throw new InternalError();2108}21092110ObjectStreamClass desc = readClassDesc(false);2111if (!desc.isEnum()) {2112throw new InvalidClassException("non-enum class: " + desc);2113}21142115int enumHandle = handles.assign(unshared ? unsharedMarker : null);2116ClassNotFoundException resolveEx = desc.getResolveException();2117if (resolveEx != null) {2118handles.markException(enumHandle, resolveEx);2119}21202121String name = readString(false);2122Enum<?> result = null;2123Class<?> cl = desc.forClass();2124if (cl != null) {2125try {2126@SuppressWarnings("unchecked")2127Enum<?> en = Enum.valueOf((Class)cl, name);2128result = en;2129} catch (IllegalArgumentException ex) {2130throw (IOException) new InvalidObjectException(2131"enum constant " + name + " does not exist in " +2132cl).initCause(ex);2133}2134if (!unshared) {2135handles.setObject(enumHandle, result);2136}2137}21382139handles.finish(enumHandle);2140passHandle = enumHandle;2141return result;2142}21432144/**2145* Reads and returns "ordinary" (i.e., not a String, Class,2146* ObjectStreamClass, array, or enum constant) object, or null if object's2147* class is unresolvable (in which case a ClassNotFoundException will be2148* associated with object's handle). Sets passHandle to object's assigned2149* handle.2150*/2151private Object readOrdinaryObject(boolean unshared)2152throws IOException2153{2154if (bin.readByte() != TC_OBJECT) {2155throw new InternalError();2156}21572158ObjectStreamClass desc = readClassDesc(false);2159desc.checkDeserialize();21602161Class<?> cl = desc.forClass();2162if (cl == String.class || cl == Class.class2163|| cl == ObjectStreamClass.class) {2164throw new InvalidClassException("invalid class descriptor");2165}21662167Object obj;2168try {2169obj = desc.isInstantiable() ? desc.newInstance() : null;2170} catch (Exception ex) {2171throw (IOException) new InvalidClassException(2172desc.forClass().getName(),2173"unable to create instance").initCause(ex);2174}21752176passHandle = handles.assign(unshared ? unsharedMarker : obj);2177ClassNotFoundException resolveEx = desc.getResolveException();2178if (resolveEx != null) {2179handles.markException(passHandle, resolveEx);2180}21812182if (desc.isExternalizable()) {2183readExternalData((Externalizable) obj, desc);2184} else {2185readSerialData(obj, desc);2186}21872188handles.finish(passHandle);21892190if (obj != null &&2191handles.lookupException(passHandle) == null &&2192desc.hasReadResolveMethod())2193{2194Object rep = desc.invokeReadResolve(obj);2195if (unshared && rep.getClass().isArray()) {2196rep = cloneArray(rep);2197}2198if (rep != obj) {2199// Filter the replacement object2200if (rep != null) {2201if (rep.getClass().isArray()) {2202filterCheck(rep.getClass(), Array.getLength(rep));2203} else {2204filterCheck(rep.getClass(), -1);2205}2206}2207handles.setObject(passHandle, obj = rep);2208}2209}22102211return obj;2212}22132214/**2215* If obj is non-null, reads externalizable data by invoking readExternal()2216* method of obj; otherwise, attempts to skip over externalizable data.2217* Expects that passHandle is set to obj's handle before this method is2218* called.2219*/2220private void readExternalData(Externalizable obj, ObjectStreamClass desc)2221throws IOException2222{2223SerialCallbackContext oldContext = curContext;2224if (oldContext != null)2225oldContext.check();2226curContext = null;2227try {2228boolean blocked = desc.hasBlockExternalData();2229if (blocked) {2230bin.setBlockDataMode(true);2231}2232if (obj != null) {2233try {2234obj.readExternal(this);2235} catch (ClassNotFoundException ex) {2236/*2237* In most cases, the handle table has already propagated2238* a CNFException to passHandle at this point; this mark2239* call is included to address cases where the readExternal2240* method has cons'ed and thrown a new CNFException of its2241* own.2242*/2243handles.markException(passHandle, ex);2244}2245}2246if (blocked) {2247skipCustomData();2248}2249} finally {2250if (oldContext != null)2251oldContext.check();2252curContext = oldContext;2253}2254/*2255* At this point, if the externalizable data was not written in2256* block-data form and either the externalizable class doesn't exist2257* locally (i.e., obj == null) or readExternal() just threw a2258* CNFException, then the stream is probably in an inconsistent state,2259* since some (or all) of the externalizable data may not have been2260* consumed. Since there's no "correct" action to take in this case,2261* we mimic the behavior of past serialization implementations and2262* blindly hope that the stream is in sync; if it isn't and additional2263* externalizable data remains in the stream, a subsequent read will2264* most likely throw a StreamCorruptedException.2265*/2266}22672268/**2269* Reads (or attempts to skip, if obj is null or is tagged with a2270* ClassNotFoundException) instance data for each serializable class of2271* object in stream, from superclass to subclass. Expects that passHandle2272* is set to obj's handle before this method is called.2273*/2274private void readSerialData(Object obj, ObjectStreamClass desc)2275throws IOException2276{2277ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();2278for (int i = 0; i < slots.length; i++) {2279ObjectStreamClass slotDesc = slots[i].desc;22802281if (slots[i].hasData) {2282if (obj == null || handles.lookupException(passHandle) != null) {2283defaultReadFields(null, slotDesc); // skip field values2284} else if (slotDesc.hasReadObjectMethod()) {2285ThreadDeath t = null;2286boolean reset = false;2287SerialCallbackContext oldContext = curContext;2288if (oldContext != null)2289oldContext.check();2290try {2291curContext = new SerialCallbackContext(obj, slotDesc);22922293bin.setBlockDataMode(true);2294slotDesc.invokeReadObject(obj, this);2295} catch (ClassNotFoundException ex) {2296/*2297* In most cases, the handle table has already2298* propagated a CNFException to passHandle at this2299* point; this mark call is included to address cases2300* where the custom readObject method has cons'ed and2301* thrown a new CNFException of its own.2302*/2303handles.markException(passHandle, ex);2304} finally {2305do {2306try {2307curContext.setUsed();2308if (oldContext!= null)2309oldContext.check();2310curContext = oldContext;2311reset = true;2312} catch (ThreadDeath x) {2313t = x; // defer until reset is true2314}2315} while (!reset);2316if (t != null)2317throw t;2318}23192320/*2321* defaultDataEnd may have been set indirectly by custom2322* readObject() method when calling defaultReadObject() or2323* readFields(); clear it to restore normal read behavior.2324*/2325defaultDataEnd = false;2326} else {2327defaultReadFields(obj, slotDesc);2328}23292330if (slotDesc.hasWriteObjectData()) {2331skipCustomData();2332} else {2333bin.setBlockDataMode(false);2334}2335} else {2336if (obj != null &&2337slotDesc.hasReadObjectNoDataMethod() &&2338handles.lookupException(passHandle) == null)2339{2340slotDesc.invokeReadObjectNoData(obj);2341}2342}2343}2344}23452346/**2347* Skips over all block data and objects until TC_ENDBLOCKDATA is2348* encountered.2349*/2350private void skipCustomData() throws IOException {2351int oldHandle = passHandle;2352for (;;) {2353if (bin.getBlockDataMode()) {2354bin.skipBlockData();2355bin.setBlockDataMode(false);2356}2357switch (bin.peekByte()) {2358case TC_BLOCKDATA:2359case TC_BLOCKDATALONG:2360bin.setBlockDataMode(true);2361break;23622363case TC_ENDBLOCKDATA:2364bin.readByte();2365passHandle = oldHandle;2366return;23672368default:2369readObject0(Object.class, false);2370break;2371}2372}2373}23742375/**2376* Reads in values of serializable fields declared by given class2377* descriptor. If obj is non-null, sets field values in obj. Expects that2378* passHandle is set to obj's handle before this method is called.2379*/2380private void defaultReadFields(Object obj, ObjectStreamClass desc)2381throws IOException2382{2383Class<?> cl = desc.forClass();2384if (cl != null && obj != null && !cl.isInstance(obj)) {2385throw new ClassCastException();2386}23872388int primDataSize = desc.getPrimDataSize();2389if (primVals == null || primVals.length < primDataSize) {2390primVals = new byte[primDataSize];2391}2392bin.readFully(primVals, 0, primDataSize, false);2393if (obj != null) {2394desc.setPrimFieldValues(obj, primVals);2395}23962397int objHandle = passHandle;2398ObjectStreamField[] fields = desc.getFields(false);2399Object[] objVals = new Object[desc.getNumObjFields()];2400int numPrimFields = fields.length - objVals.length;2401for (int i = 0; i < objVals.length; i++) {2402ObjectStreamField f = fields[numPrimFields + i];2403objVals[i] = readObject0(Object.class, f.isUnshared());2404if (f.getField() != null) {2405handles.markDependency(objHandle, passHandle);2406}2407}2408if (obj != null) {2409desc.setObjFieldValues(obj, objVals);2410}2411passHandle = objHandle;2412}24132414/**2415* Reads in and returns IOException that caused serialization to abort.2416* All stream state is discarded prior to reading in fatal exception. Sets2417* passHandle to fatal exception's handle.2418*/2419private IOException readFatalException() throws IOException {2420if (bin.readByte() != TC_EXCEPTION) {2421throw new InternalError();2422}2423clear();2424return (IOException) readObject0(Object.class, false);2425}24262427/**2428* If recursion depth is 0, clears internal data structures; otherwise,2429* throws a StreamCorruptedException. This method is called when a2430* TC_RESET typecode is encountered.2431*/2432private void handleReset() throws StreamCorruptedException {2433if (depth > 0) {2434throw new StreamCorruptedException(2435"unexpected reset; recursion depth: " + depth);2436}2437clear();2438}24392440/**2441* Converts specified span of bytes into float values.2442*/2443// REMIND: remove once hotspot inlines Float.intBitsToFloat2444private static native void bytesToFloats(byte[] src, int srcpos,2445float[] dst, int dstpos,2446int nfloats);24472448/**2449* Converts specified span of bytes into double values.2450*/2451// REMIND: remove once hotspot inlines Double.longBitsToDouble2452private static native void bytesToDoubles(byte[] src, int srcpos,2453double[] dst, int dstpos,2454int ndoubles);24552456/**2457* Returns first non-privileged class loader on the stack (excluding2458* reflection generated frames) or the extension class loader if only2459* class loaded by the boot class loader and extension class loader are2460* found on the stack. This method is also called via reflection by the2461* following RMI-IIOP class:2462*2463* com.sun.corba.se.internal.util.JDKClassLoader2464*2465* This method should not be removed or its signature changed without2466* corresponding modifications to the above class.2467*/2468private static ClassLoader latestUserDefinedLoader() {2469return sun.misc.VM.latestUserDefinedLoader();2470}24712472/**2473* Default GetField implementation.2474*/2475private class GetFieldImpl extends GetField {24762477/** class descriptor describing serializable fields */2478private final ObjectStreamClass desc;2479/** primitive field values */2480private final byte[] primVals;2481/** object field values */2482private final Object[] objVals;2483/** object field value handles */2484private final int[] objHandles;24852486/**2487* Creates GetFieldImpl object for reading fields defined in given2488* class descriptor.2489*/2490GetFieldImpl(ObjectStreamClass desc) {2491this.desc = desc;2492primVals = new byte[desc.getPrimDataSize()];2493objVals = new Object[desc.getNumObjFields()];2494objHandles = new int[objVals.length];2495}24962497public ObjectStreamClass getObjectStreamClass() {2498return desc;2499}25002501public boolean defaulted(String name) throws IOException {2502return (getFieldOffset(name, null) < 0);2503}25042505public boolean get(String name, boolean val) throws IOException {2506int off = getFieldOffset(name, Boolean.TYPE);2507return (off >= 0) ? Bits.getBoolean(primVals, off) : val;2508}25092510public byte get(String name, byte val) throws IOException {2511int off = getFieldOffset(name, Byte.TYPE);2512return (off >= 0) ? primVals[off] : val;2513}25142515public char get(String name, char val) throws IOException {2516int off = getFieldOffset(name, Character.TYPE);2517return (off >= 0) ? Bits.getChar(primVals, off) : val;2518}25192520public short get(String name, short val) throws IOException {2521int off = getFieldOffset(name, Short.TYPE);2522return (off >= 0) ? Bits.getShort(primVals, off) : val;2523}25242525public int get(String name, int val) throws IOException {2526int off = getFieldOffset(name, Integer.TYPE);2527return (off >= 0) ? Bits.getInt(primVals, off) : val;2528}25292530public float get(String name, float val) throws IOException {2531int off = getFieldOffset(name, Float.TYPE);2532return (off >= 0) ? Bits.getFloat(primVals, off) : val;2533}25342535public long get(String name, long val) throws IOException {2536int off = getFieldOffset(name, Long.TYPE);2537return (off >= 0) ? Bits.getLong(primVals, off) : val;2538}25392540public double get(String name, double val) throws IOException {2541int off = getFieldOffset(name, Double.TYPE);2542return (off >= 0) ? Bits.getDouble(primVals, off) : val;2543}25442545public Object get(String name, Object val) throws IOException {2546int off = getFieldOffset(name, Object.class);2547if (off >= 0) {2548int objHandle = objHandles[off];2549handles.markDependency(passHandle, objHandle);2550return (handles.lookupException(objHandle) == null) ?2551objVals[off] : null;2552} else {2553return val;2554}2555}25562557/**2558* Reads primitive and object field values from stream.2559*/2560void readFields() throws IOException {2561bin.readFully(primVals, 0, primVals.length, false);25622563int oldHandle = passHandle;2564ObjectStreamField[] fields = desc.getFields(false);2565int numPrimFields = fields.length - objVals.length;2566for (int i = 0; i < objVals.length; i++) {2567objVals[i] =2568readObject0(Object.class, fields[numPrimFields + i].isUnshared());2569objHandles[i] = passHandle;2570}2571passHandle = oldHandle;2572}25732574/**2575* Returns offset of field with given name and type. A specified type2576* of null matches all types, Object.class matches all non-primitive2577* types, and any other non-null type matches assignable types only.2578* If no matching field is found in the (incoming) class2579* descriptor but a matching field is present in the associated local2580* class descriptor, returns -1. Throws IllegalArgumentException if2581* neither incoming nor local class descriptor contains a match.2582*/2583private int getFieldOffset(String name, Class<?> type) {2584ObjectStreamField field = desc.getField(name, type);2585if (field != null) {2586return field.getOffset();2587} else if (desc.getLocalDesc().getField(name, type) != null) {2588return -1;2589} else {2590throw new IllegalArgumentException("no such field " + name +2591" with type " + type);2592}2593}2594}25952596/**2597* Prioritized list of callbacks to be performed once object graph has been2598* completely deserialized.2599*/2600private static class ValidationList {26012602private static class Callback {2603final ObjectInputValidation obj;2604final int priority;2605Callback next;2606final AccessControlContext acc;26072608Callback(ObjectInputValidation obj, int priority, Callback next,2609AccessControlContext acc)2610{2611this.obj = obj;2612this.priority = priority;2613this.next = next;2614this.acc = acc;2615}2616}26172618/** linked list of callbacks */2619private Callback list;26202621/**2622* Creates new (empty) ValidationList.2623*/2624ValidationList() {2625}26262627/**2628* Registers callback. Throws InvalidObjectException if callback2629* object is null.2630*/2631void register(ObjectInputValidation obj, int priority)2632throws InvalidObjectException2633{2634if (obj == null) {2635throw new InvalidObjectException("null callback");2636}26372638Callback prev = null, cur = list;2639while (cur != null && priority < cur.priority) {2640prev = cur;2641cur = cur.next;2642}2643AccessControlContext acc = AccessController.getContext();2644if (prev != null) {2645prev.next = new Callback(obj, priority, cur, acc);2646} else {2647list = new Callback(obj, priority, list, acc);2648}2649}26502651/**2652* Invokes all registered callbacks and clears the callback list.2653* Callbacks with higher priorities are called first; those with equal2654* priorities may be called in any order. If any of the callbacks2655* throws an InvalidObjectException, the callback process is terminated2656* and the exception propagated upwards.2657*/2658void doCallbacks() throws InvalidObjectException {2659try {2660while (list != null) {2661AccessController.doPrivileged(2662new PrivilegedExceptionAction<Void>()2663{2664public Void run() throws InvalidObjectException {2665list.obj.validateObject();2666return null;2667}2668}, list.acc);2669list = list.next;2670}2671} catch (PrivilegedActionException ex) {2672list = null;2673throw (InvalidObjectException) ex.getException();2674}2675}26762677/**2678* Resets the callback list to its initial (empty) state.2679*/2680public void clear() {2681list = null;2682}2683}26842685/**2686* Hold a snapshot of values to be passed to an ObjectInputFilter.2687*/2688static class FilterValues implements ObjectInputFilter.FilterInfo {2689final Class<?> clazz;2690final long arrayLength;2691final long totalObjectRefs;2692final long depth;2693final long streamBytes;26942695public FilterValues(Class<?> clazz, long arrayLength, long totalObjectRefs,2696long depth, long streamBytes) {2697this.clazz = clazz;2698this.arrayLength = arrayLength;2699this.totalObjectRefs = totalObjectRefs;2700this.depth = depth;2701this.streamBytes = streamBytes;2702}27032704@Override2705public Class<?> serialClass() {2706return clazz;2707}27082709@Override2710public long arrayLength() {2711return arrayLength;2712}27132714@Override2715public long references() {2716return totalObjectRefs;2717}27182719@Override2720public long depth() {2721return depth;2722}27232724@Override2725public long streamBytes() {2726return streamBytes;2727}2728}27292730/**2731* Input stream supporting single-byte peek operations.2732*/2733private static class PeekInputStream extends InputStream {27342735/** underlying stream */2736private final InputStream in;2737/** peeked byte */2738private int peekb = -1;2739/** total bytes read from the stream */2740private long totalBytesRead = 0;27412742/**2743* Creates new PeekInputStream on top of given underlying stream.2744*/2745PeekInputStream(InputStream in) {2746this.in = in;2747}27482749/**2750* Peeks at next byte value in stream. Similar to read(), except2751* that it does not consume the read value.2752*/2753int peek() throws IOException {2754if (peekb >= 0) {2755return peekb;2756}2757peekb = in.read();2758totalBytesRead += peekb >= 0 ? 1 : 0;2759return peekb;2760}27612762public int read() throws IOException {2763if (peekb >= 0) {2764int v = peekb;2765peekb = -1;2766return v;2767} else {2768int nbytes = in.read();2769totalBytesRead += nbytes >= 0 ? 1 : 0;2770return nbytes;2771}2772}27732774public int read(byte[] b, int off, int len) throws IOException {2775int nbytes;2776if (len == 0) {2777return 0;2778} else if (peekb < 0) {2779nbytes = in.read(b, off, len);2780totalBytesRead += nbytes >= 0 ? nbytes : 0;2781return nbytes;2782} else {2783b[off++] = (byte) peekb;2784len--;2785peekb = -1;2786nbytes = in.read(b, off, len);2787totalBytesRead += nbytes >= 0 ? nbytes : 0;2788return (nbytes >= 0) ? (nbytes + 1) : 1;2789}2790}27912792void readFully(byte[] b, int off, int len) throws IOException {2793int n = 0;2794while (n < len) {2795int count = read(b, off + n, len - n);2796if (count < 0) {2797throw new EOFException();2798}2799n += count;2800}2801}28022803public long skip(long n) throws IOException {2804if (n <= 0) {2805return 0;2806}2807int skipped = 0;2808if (peekb >= 0) {2809peekb = -1;2810skipped++;2811n--;2812}2813n = skipped + in.skip(n);2814totalBytesRead += n;2815return n;2816}28172818public int available() throws IOException {2819return in.available() + ((peekb >= 0) ? 1 : 0);2820}28212822public void close() throws IOException {2823in.close();2824}28252826public long getBytesRead() {2827return totalBytesRead;2828}2829}28302831/**2832* Input stream with two modes: in default mode, inputs data written in the2833* same format as DataOutputStream; in "block data" mode, inputs data2834* bracketed by block data markers (see object serialization specification2835* for details). Buffering depends on block data mode: when in default2836* mode, no data is buffered in advance; when in block data mode, all data2837* for the current data block is read in at once (and buffered).2838*/2839private class BlockDataInputStream2840extends InputStream implements DataInput2841{2842/** maximum data block length */2843private static final int MAX_BLOCK_SIZE = 1024;2844/** maximum data block header length */2845private static final int MAX_HEADER_SIZE = 5;2846/** (tunable) length of char buffer (for reading strings) */2847private static final int CHAR_BUF_SIZE = 256;2848/** readBlockHeader() return value indicating header read may block */2849private static final int HEADER_BLOCKED = -2;28502851/** buffer for reading general/block data */2852private final byte[] buf = new byte[MAX_BLOCK_SIZE];2853/** buffer for reading block data headers */2854private final byte[] hbuf = new byte[MAX_HEADER_SIZE];2855/** char buffer for fast string reads */2856private final char[] cbuf = new char[CHAR_BUF_SIZE];28572858/** block data mode */2859private boolean blkmode = false;28602861// block data state fields; values meaningful only when blkmode true2862/** current offset into buf */2863private int pos = 0;2864/** end offset of valid data in buf, or -1 if no more block data */2865private int end = -1;2866/** number of bytes in current block yet to be read from stream */2867private int unread = 0;28682869/** underlying stream (wrapped in peekable filter stream) */2870private final PeekInputStream in;2871/** loopback stream (for data reads that span data blocks) */2872private final DataInputStream din;28732874/**2875* Creates new BlockDataInputStream on top of given underlying stream.2876* Block data mode is turned off by default.2877*/2878BlockDataInputStream(InputStream in) {2879this.in = new PeekInputStream(in);2880din = new DataInputStream(this);2881}28822883/**2884* Sets block data mode to the given mode (true == on, false == off)2885* and returns the previous mode value. If the new mode is the same as2886* the old mode, no action is taken. Throws IllegalStateException if2887* block data mode is being switched from on to off while unconsumed2888* block data is still present in the stream.2889*/2890boolean setBlockDataMode(boolean newmode) throws IOException {2891if (blkmode == newmode) {2892return blkmode;2893}2894if (newmode) {2895pos = 0;2896end = 0;2897unread = 0;2898} else if (pos < end) {2899throw new IllegalStateException("unread block data");2900}2901blkmode = newmode;2902return !blkmode;2903}29042905/**2906* Returns true if the stream is currently in block data mode, false2907* otherwise.2908*/2909boolean getBlockDataMode() {2910return blkmode;2911}29122913/**2914* If in block data mode, skips to the end of the current group of data2915* blocks (but does not unset block data mode). If not in block data2916* mode, throws an IllegalStateException.2917*/2918void skipBlockData() throws IOException {2919if (!blkmode) {2920throw new IllegalStateException("not in block data mode");2921}2922while (end >= 0) {2923refill();2924}2925}29262927/**2928* Attempts to read in the next block data header (if any). If2929* canBlock is false and a full header cannot be read without possibly2930* blocking, returns HEADER_BLOCKED, else if the next element in the2931* stream is a block data header, returns the block data length2932* specified by the header, else returns -1.2933*/2934private int readBlockHeader(boolean canBlock) throws IOException {2935if (defaultDataEnd) {2936/*2937* Fix for 4360508: stream is currently at the end of a field2938* value block written via default serialization; since there2939* is no terminating TC_ENDBLOCKDATA tag, simulate2940* end-of-custom-data behavior explicitly.2941*/2942return -1;2943}2944try {2945for (;;) {2946int avail = canBlock ? Integer.MAX_VALUE : in.available();2947if (avail == 0) {2948return HEADER_BLOCKED;2949}29502951int tc = in.peek();2952switch (tc) {2953case TC_BLOCKDATA:2954if (avail < 2) {2955return HEADER_BLOCKED;2956}2957in.readFully(hbuf, 0, 2);2958return hbuf[1] & 0xFF;29592960case TC_BLOCKDATALONG:2961if (avail < 5) {2962return HEADER_BLOCKED;2963}2964in.readFully(hbuf, 0, 5);2965int len = Bits.getInt(hbuf, 1);2966if (len < 0) {2967throw new StreamCorruptedException(2968"illegal block data header length: " +2969len);2970}2971return len;29722973/*2974* TC_RESETs may occur in between data blocks.2975* Unfortunately, this case must be parsed at a lower2976* level than other typecodes, since primitive data2977* reads may span data blocks separated by a TC_RESET.2978*/2979case TC_RESET:2980in.read();2981handleReset();2982break;29832984default:2985if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {2986throw new StreamCorruptedException(2987String.format("invalid type code: %02X",2988tc));2989}2990return -1;2991}2992}2993} catch (EOFException ex) {2994throw new StreamCorruptedException(2995"unexpected EOF while reading block data header");2996}2997}29982999/**3000* Refills internal buffer buf with block data. Any data in buf at the3001* time of the call is considered consumed. Sets the pos, end, and3002* unread fields to reflect the new amount of available block data; if3003* the next element in the stream is not a data block, sets pos and3004* unread to 0 and end to -1.3005*/3006private void refill() throws IOException {3007try {3008do {3009pos = 0;3010if (unread > 0) {3011int n =3012in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));3013if (n >= 0) {3014end = n;3015unread -= n;3016} else {3017throw new StreamCorruptedException(3018"unexpected EOF in middle of data block");3019}3020} else {3021int n = readBlockHeader(true);3022if (n >= 0) {3023end = 0;3024unread = n;3025} else {3026end = -1;3027unread = 0;3028}3029}3030} while (pos == end);3031} catch (IOException ex) {3032pos = 0;3033end = -1;3034unread = 0;3035throw ex;3036}3037}30383039/**3040* If in block data mode, returns the number of unconsumed bytes3041* remaining in the current data block. If not in block data mode,3042* throws an IllegalStateException.3043*/3044int currentBlockRemaining() {3045if (blkmode) {3046return (end >= 0) ? (end - pos) + unread : 0;3047} else {3048throw new IllegalStateException();3049}3050}30513052/**3053* Peeks at (but does not consume) and returns the next byte value in3054* the stream, or -1 if the end of the stream/block data (if in block3055* data mode) has been reached.3056*/3057int peek() throws IOException {3058if (blkmode) {3059if (pos == end) {3060refill();3061}3062return (end >= 0) ? (buf[pos] & 0xFF) : -1;3063} else {3064return in.peek();3065}3066}30673068/**3069* Peeks at (but does not consume) and returns the next byte value in3070* the stream, or throws EOFException if end of stream/block data has3071* been reached.3072*/3073byte peekByte() throws IOException {3074int val = peek();3075if (val < 0) {3076throw new EOFException();3077}3078return (byte) val;3079}308030813082/* ----------------- generic input stream methods ------------------ */3083/*3084* The following methods are equivalent to their counterparts in3085* InputStream, except that they interpret data block boundaries and3086* read the requested data from within data blocks when in block data3087* mode.3088*/30893090public int read() throws IOException {3091if (blkmode) {3092if (pos == end) {3093refill();3094}3095return (end >= 0) ? (buf[pos++] & 0xFF) : -1;3096} else {3097return in.read();3098}3099}31003101public int read(byte[] b, int off, int len) throws IOException {3102return read(b, off, len, false);3103}31043105public long skip(long len) throws IOException {3106long remain = len;3107while (remain > 0) {3108if (blkmode) {3109if (pos == end) {3110refill();3111}3112if (end < 0) {3113break;3114}3115int nread = (int) Math.min(remain, end - pos);3116remain -= nread;3117pos += nread;3118} else {3119int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);3120if ((nread = in.read(buf, 0, nread)) < 0) {3121break;3122}3123remain -= nread;3124}3125}3126return len - remain;3127}31283129public int available() throws IOException {3130if (blkmode) {3131if ((pos == end) && (unread == 0)) {3132int n;3133while ((n = readBlockHeader(false)) == 0) ;3134switch (n) {3135case HEADER_BLOCKED:3136break;31373138case -1:3139pos = 0;3140end = -1;3141break;31423143default:3144pos = 0;3145end = 0;3146unread = n;3147break;3148}3149}3150// avoid unnecessary call to in.available() if possible3151int unreadAvail = (unread > 0) ?3152Math.min(in.available(), unread) : 0;3153return (end >= 0) ? (end - pos) + unreadAvail : 0;3154} else {3155return in.available();3156}3157}31583159public void close() throws IOException {3160if (blkmode) {3161pos = 0;3162end = -1;3163unread = 0;3164}3165in.close();3166}31673168/**3169* Attempts to read len bytes into byte array b at offset off. Returns3170* the number of bytes read, or -1 if the end of stream/block data has3171* been reached. If copy is true, reads values into an intermediate3172* buffer before copying them to b (to avoid exposing a reference to3173* b).3174*/3175int read(byte[] b, int off, int len, boolean copy) throws IOException {3176if (len == 0) {3177return 0;3178} else if (blkmode) {3179if (pos == end) {3180refill();3181}3182if (end < 0) {3183return -1;3184}3185int nread = Math.min(len, end - pos);3186System.arraycopy(buf, pos, b, off, nread);3187pos += nread;3188return nread;3189} else if (copy) {3190int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));3191if (nread > 0) {3192System.arraycopy(buf, 0, b, off, nread);3193}3194return nread;3195} else {3196return in.read(b, off, len);3197}3198}31993200/* ----------------- primitive data input methods ------------------ */3201/*3202* The following methods are equivalent to their counterparts in3203* DataInputStream, except that they interpret data block boundaries3204* and read the requested data from within data blocks when in block3205* data mode.3206*/32073208public void readFully(byte[] b) throws IOException {3209readFully(b, 0, b.length, false);3210}32113212public void readFully(byte[] b, int off, int len) throws IOException {3213readFully(b, off, len, false);3214}32153216public void readFully(byte[] b, int off, int len, boolean copy)3217throws IOException3218{3219while (len > 0) {3220int n = read(b, off, len, copy);3221if (n < 0) {3222throw new EOFException();3223}3224off += n;3225len -= n;3226}3227}32283229public int skipBytes(int n) throws IOException {3230return din.skipBytes(n);3231}32323233public boolean readBoolean() throws IOException {3234int v = read();3235if (v < 0) {3236throw new EOFException();3237}3238return (v != 0);3239}32403241public byte readByte() throws IOException {3242int v = read();3243if (v < 0) {3244throw new EOFException();3245}3246return (byte) v;3247}32483249public int readUnsignedByte() throws IOException {3250int v = read();3251if (v < 0) {3252throw new EOFException();3253}3254return v;3255}32563257public char readChar() throws IOException {3258if (!blkmode) {3259pos = 0;3260in.readFully(buf, 0, 2);3261} else if (end - pos < 2) {3262return din.readChar();3263}3264char v = Bits.getChar(buf, pos);3265pos += 2;3266return v;3267}32683269public short readShort() throws IOException {3270if (!blkmode) {3271pos = 0;3272in.readFully(buf, 0, 2);3273} else if (end - pos < 2) {3274return din.readShort();3275}3276short v = Bits.getShort(buf, pos);3277pos += 2;3278return v;3279}32803281public int readUnsignedShort() throws IOException {3282if (!blkmode) {3283pos = 0;3284in.readFully(buf, 0, 2);3285} else if (end - pos < 2) {3286return din.readUnsignedShort();3287}3288int v = Bits.getShort(buf, pos) & 0xFFFF;3289pos += 2;3290return v;3291}32923293public int readInt() throws IOException {3294if (!blkmode) {3295pos = 0;3296in.readFully(buf, 0, 4);3297} else if (end - pos < 4) {3298return din.readInt();3299}3300int v = Bits.getInt(buf, pos);3301pos += 4;3302return v;3303}33043305public float readFloat() throws IOException {3306if (!blkmode) {3307pos = 0;3308in.readFully(buf, 0, 4);3309} else if (end - pos < 4) {3310return din.readFloat();3311}3312float v = Bits.getFloat(buf, pos);3313pos += 4;3314return v;3315}33163317public long readLong() throws IOException {3318if (!blkmode) {3319pos = 0;3320in.readFully(buf, 0, 8);3321} else if (end - pos < 8) {3322return din.readLong();3323}3324long v = Bits.getLong(buf, pos);3325pos += 8;3326return v;3327}33283329public double readDouble() throws IOException {3330if (!blkmode) {3331pos = 0;3332in.readFully(buf, 0, 8);3333} else if (end - pos < 8) {3334return din.readDouble();3335}3336double v = Bits.getDouble(buf, pos);3337pos += 8;3338return v;3339}33403341public String readUTF() throws IOException {3342return readUTFBody(readUnsignedShort());3343}33443345@SuppressWarnings("deprecation")3346public String readLine() throws IOException {3347return din.readLine(); // deprecated, not worth optimizing3348}33493350/* -------------- primitive data array input methods --------------- */3351/*3352* The following methods read in spans of primitive data values.3353* Though equivalent to calling the corresponding primitive read3354* methods repeatedly, these methods are optimized for reading groups3355* of primitive data values more efficiently.3356*/33573358void readBooleans(boolean[] v, int off, int len) throws IOException {3359int stop, endoff = off + len;3360while (off < endoff) {3361if (!blkmode) {3362int span = Math.min(endoff - off, MAX_BLOCK_SIZE);3363in.readFully(buf, 0, span);3364stop = off + span;3365pos = 0;3366} else if (end - pos < 1) {3367v[off++] = din.readBoolean();3368continue;3369} else {3370stop = Math.min(endoff, off + end - pos);3371}33723373while (off < stop) {3374v[off++] = Bits.getBoolean(buf, pos++);3375}3376}3377}33783379void readChars(char[] v, int off, int len) throws IOException {3380int stop, endoff = off + len;3381while (off < endoff) {3382if (!blkmode) {3383int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);3384in.readFully(buf, 0, span << 1);3385stop = off + span;3386pos = 0;3387} else if (end - pos < 2) {3388v[off++] = din.readChar();3389continue;3390} else {3391stop = Math.min(endoff, off + ((end - pos) >> 1));3392}33933394while (off < stop) {3395v[off++] = Bits.getChar(buf, pos);3396pos += 2;3397}3398}3399}34003401void readShorts(short[] v, int off, int len) throws IOException {3402int stop, endoff = off + len;3403while (off < endoff) {3404if (!blkmode) {3405int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);3406in.readFully(buf, 0, span << 1);3407stop = off + span;3408pos = 0;3409} else if (end - pos < 2) {3410v[off++] = din.readShort();3411continue;3412} else {3413stop = Math.min(endoff, off + ((end - pos) >> 1));3414}34153416while (off < stop) {3417v[off++] = Bits.getShort(buf, pos);3418pos += 2;3419}3420}3421}34223423void readInts(int[] v, int off, int len) throws IOException {3424int stop, endoff = off + len;3425while (off < endoff) {3426if (!blkmode) {3427int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);3428in.readFully(buf, 0, span << 2);3429stop = off + span;3430pos = 0;3431} else if (end - pos < 4) {3432v[off++] = din.readInt();3433continue;3434} else {3435stop = Math.min(endoff, off + ((end - pos) >> 2));3436}34373438while (off < stop) {3439v[off++] = Bits.getInt(buf, pos);3440pos += 4;3441}3442}3443}34443445void readFloats(float[] v, int off, int len) throws IOException {3446int span, endoff = off + len;3447while (off < endoff) {3448if (!blkmode) {3449span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);3450in.readFully(buf, 0, span << 2);3451pos = 0;3452} else if (end - pos < 4) {3453v[off++] = din.readFloat();3454continue;3455} else {3456span = Math.min(endoff - off, ((end - pos) >> 2));3457}34583459bytesToFloats(buf, pos, v, off, span);3460off += span;3461pos += span << 2;3462}3463}34643465void readLongs(long[] v, int off, int len) throws IOException {3466int stop, endoff = off + len;3467while (off < endoff) {3468if (!blkmode) {3469int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);3470in.readFully(buf, 0, span << 3);3471stop = off + span;3472pos = 0;3473} else if (end - pos < 8) {3474v[off++] = din.readLong();3475continue;3476} else {3477stop = Math.min(endoff, off + ((end - pos) >> 3));3478}34793480while (off < stop) {3481v[off++] = Bits.getLong(buf, pos);3482pos += 8;3483}3484}3485}34863487void readDoubles(double[] v, int off, int len) throws IOException {3488int span, endoff = off + len;3489while (off < endoff) {3490if (!blkmode) {3491span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);3492in.readFully(buf, 0, span << 3);3493pos = 0;3494} else if (end - pos < 8) {3495v[off++] = din.readDouble();3496continue;3497} else {3498span = Math.min(endoff - off, ((end - pos) >> 3));3499}35003501bytesToDoubles(buf, pos, v, off, span);3502off += span;3503pos += span << 3;3504}3505}35063507/**3508* Reads in string written in "long" UTF format. "Long" UTF format is3509* identical to standard UTF, except that it uses an 8 byte header3510* (instead of the standard 2 bytes) to convey the UTF encoding length.3511*/3512String readLongUTF() throws IOException {3513return readUTFBody(readLong());3514}35153516/**3517* Reads in the "body" (i.e., the UTF representation minus the 2-byte3518* or 8-byte length header) of a UTF encoding, which occupies the next3519* utflen bytes.3520*/3521private String readUTFBody(long utflen) throws IOException {3522StringBuilder sbuf;3523if (utflen > 0 && utflen < Integer.MAX_VALUE) {3524// a reasonable initial capacity based on the UTF length3525int initialCapacity = Math.min((int)utflen, 0xFFFF);3526sbuf = new StringBuilder(initialCapacity);3527} else {3528sbuf = new StringBuilder();3529}35303531if (!blkmode) {3532end = pos = 0;3533}35343535while (utflen > 0) {3536int avail = end - pos;3537if (avail >= 3 || (long) avail == utflen) {3538utflen -= readUTFSpan(sbuf, utflen);3539} else {3540if (blkmode) {3541// near block boundary, read one byte at a time3542utflen -= readUTFChar(sbuf, utflen);3543} else {3544// shift and refill buffer manually3545if (avail > 0) {3546System.arraycopy(buf, pos, buf, 0, avail);3547}3548pos = 0;3549end = (int) Math.min(MAX_BLOCK_SIZE, utflen);3550in.readFully(buf, avail, end - avail);3551}3552}3553}35543555return sbuf.toString();3556}35573558/**3559* Reads span of UTF-encoded characters out of internal buffer3560* (starting at offset pos and ending at or before offset end),3561* consuming no more than utflen bytes. Appends read characters to3562* sbuf. Returns the number of bytes consumed.3563*/3564private long readUTFSpan(StringBuilder sbuf, long utflen)3565throws IOException3566{3567int cpos = 0;3568int start = pos;3569int avail = Math.min(end - pos, CHAR_BUF_SIZE);3570// stop short of last char unless all of utf bytes in buffer3571int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);3572boolean outOfBounds = false;35733574try {3575while (pos < stop) {3576int b1, b2, b3;3577b1 = buf[pos++] & 0xFF;3578switch (b1 >> 4) {3579case 0:3580case 1:3581case 2:3582case 3:3583case 4:3584case 5:3585case 6:3586case 7: // 1 byte format: 0xxxxxxx3587cbuf[cpos++] = (char) b1;3588break;35893590case 12:3591case 13: // 2 byte format: 110xxxxx 10xxxxxx3592b2 = buf[pos++];3593if ((b2 & 0xC0) != 0x80) {3594throw new UTFDataFormatException();3595}3596cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |3597((b2 & 0x3F) << 0));3598break;35993600case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx3601b3 = buf[pos + 1];3602b2 = buf[pos + 0];3603pos += 2;3604if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {3605throw new UTFDataFormatException();3606}3607cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |3608((b2 & 0x3F) << 6) |3609((b3 & 0x3F) << 0));3610break;36113612default: // 10xx xxxx, 1111 xxxx3613throw new UTFDataFormatException();3614}3615}3616} catch (ArrayIndexOutOfBoundsException ex) {3617outOfBounds = true;3618} finally {3619if (outOfBounds || (pos - start) > utflen) {3620/*3621* Fix for 4450867: if a malformed utf char causes the3622* conversion loop to scan past the expected end of the utf3623* string, only consume the expected number of utf bytes.3624*/3625pos = start + (int) utflen;3626throw new UTFDataFormatException();3627}3628}36293630sbuf.append(cbuf, 0, cpos);3631return pos - start;3632}36333634/**3635* Reads in single UTF-encoded character one byte at a time, appends3636* the character to sbuf, and returns the number of bytes consumed.3637* This method is used when reading in UTF strings written in block3638* data mode to handle UTF-encoded characters which (potentially)3639* straddle block-data boundaries.3640*/3641private int readUTFChar(StringBuilder sbuf, long utflen)3642throws IOException3643{3644int b1, b2, b3;3645b1 = readByte() & 0xFF;3646switch (b1 >> 4) {3647case 0:3648case 1:3649case 2:3650case 3:3651case 4:3652case 5:3653case 6:3654case 7: // 1 byte format: 0xxxxxxx3655sbuf.append((char) b1);3656return 1;36573658case 12:3659case 13: // 2 byte format: 110xxxxx 10xxxxxx3660if (utflen < 2) {3661throw new UTFDataFormatException();3662}3663b2 = readByte();3664if ((b2 & 0xC0) != 0x80) {3665throw new UTFDataFormatException();3666}3667sbuf.append((char) (((b1 & 0x1F) << 6) |3668((b2 & 0x3F) << 0)));3669return 2;36703671case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx3672if (utflen < 3) {3673if (utflen == 2) {3674readByte(); // consume remaining byte3675}3676throw new UTFDataFormatException();3677}3678b2 = readByte();3679b3 = readByte();3680if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {3681throw new UTFDataFormatException();3682}3683sbuf.append((char) (((b1 & 0x0F) << 12) |3684((b2 & 0x3F) << 6) |3685((b3 & 0x3F) << 0)));3686return 3;36873688default: // 10xx xxxx, 1111 xxxx3689throw new UTFDataFormatException();3690}3691}36923693/**3694* Returns the number of bytes read from the input stream.3695* @return the number of bytes read from the input stream3696*/3697long getBytesRead() {3698return in.getBytesRead();3699}3700}37013702/**3703* Unsynchronized table which tracks wire handle to object mappings, as3704* well as ClassNotFoundExceptions associated with deserialized objects.3705* This class implements an exception-propagation algorithm for3706* determining which objects should have ClassNotFoundExceptions associated3707* with them, taking into account cycles and discontinuities (e.g., skipped3708* fields) in the object graph.3709*3710* <p>General use of the table is as follows: during deserialization, a3711* given object is first assigned a handle by calling the assign method.3712* This method leaves the assigned handle in an "open" state, wherein3713* dependencies on the exception status of other handles can be registered3714* by calling the markDependency method, or an exception can be directly3715* associated with the handle by calling markException. When a handle is3716* tagged with an exception, the HandleTable assumes responsibility for3717* propagating the exception to any other objects which depend3718* (transitively) on the exception-tagged object.3719*3720* <p>Once all exception information/dependencies for the handle have been3721* registered, the handle should be "closed" by calling the finish method3722* on it. The act of finishing a handle allows the exception propagation3723* algorithm to aggressively prune dependency links, lessening the3724* performance/memory impact of exception tracking.3725*3726* <p>Note that the exception propagation algorithm used depends on handles3727* being assigned/finished in LIFO order; however, for simplicity as well3728* as memory conservation, it does not enforce this constraint.3729*/3730// REMIND: add full description of exception propagation algorithm?3731private static class HandleTable {37323733/* status codes indicating whether object has associated exception */3734private static final byte STATUS_OK = 1;3735private static final byte STATUS_UNKNOWN = 2;3736private static final byte STATUS_EXCEPTION = 3;37373738/** array mapping handle -> object status */3739byte[] status;3740/** array mapping handle -> object/exception (depending on status) */3741Object[] entries;3742/** array mapping handle -> list of dependent handles (if any) */3743HandleList[] deps;3744/** lowest unresolved dependency */3745int lowDep = -1;3746/** number of handles in table */3747int size = 0;37483749/**3750* Creates handle table with the given initial capacity.3751*/3752HandleTable(int initialCapacity) {3753status = new byte[initialCapacity];3754entries = new Object[initialCapacity];3755deps = new HandleList[initialCapacity];3756}37573758/**3759* Assigns next available handle to given object, and returns assigned3760* handle. Once object has been completely deserialized (and all3761* dependencies on other objects identified), the handle should be3762* "closed" by passing it to finish().3763*/3764int assign(Object obj) {3765if (size >= entries.length) {3766grow();3767}3768status[size] = STATUS_UNKNOWN;3769entries[size] = obj;3770return size++;3771}37723773/**3774* Registers a dependency (in exception status) of one handle on3775* another. The dependent handle must be "open" (i.e., assigned, but3776* not finished yet). No action is taken if either dependent or target3777* handle is NULL_HANDLE.3778*/3779void markDependency(int dependent, int target) {3780if (dependent == NULL_HANDLE || target == NULL_HANDLE) {3781return;3782}3783switch (status[dependent]) {37843785case STATUS_UNKNOWN:3786switch (status[target]) {3787case STATUS_OK:3788// ignore dependencies on objs with no exception3789break;37903791case STATUS_EXCEPTION:3792// eagerly propagate exception3793markException(dependent,3794(ClassNotFoundException) entries[target]);3795break;37963797case STATUS_UNKNOWN:3798// add to dependency list of target3799if (deps[target] == null) {3800deps[target] = new HandleList();3801}3802deps[target].add(dependent);38033804// remember lowest unresolved target seen3805if (lowDep < 0 || lowDep > target) {3806lowDep = target;3807}3808break;38093810default:3811throw new InternalError();3812}3813break;38143815case STATUS_EXCEPTION:3816break;38173818default:3819throw new InternalError();3820}3821}38223823/**3824* Associates a ClassNotFoundException (if one not already associated)3825* with the currently active handle and propagates it to other3826* referencing objects as appropriate. The specified handle must be3827* "open" (i.e., assigned, but not finished yet).3828*/3829void markException(int handle, ClassNotFoundException ex) {3830switch (status[handle]) {3831case STATUS_UNKNOWN:3832status[handle] = STATUS_EXCEPTION;3833entries[handle] = ex;38343835// propagate exception to dependents3836HandleList dlist = deps[handle];3837if (dlist != null) {3838int ndeps = dlist.size();3839for (int i = 0; i < ndeps; i++) {3840markException(dlist.get(i), ex);3841}3842deps[handle] = null;3843}3844break;38453846case STATUS_EXCEPTION:3847break;38483849default:3850throw new InternalError();3851}3852}38533854/**3855* Marks given handle as finished, meaning that no new dependencies3856* will be marked for handle. Calls to the assign and finish methods3857* must occur in LIFO order.3858*/3859void finish(int handle) {3860int end;3861if (lowDep < 0) {3862// no pending unknowns, only resolve current handle3863end = handle + 1;3864} else if (lowDep >= handle) {3865// pending unknowns now clearable, resolve all upward handles3866end = size;3867lowDep = -1;3868} else {3869// unresolved backrefs present, can't resolve anything yet3870return;3871}38723873// change STATUS_UNKNOWN -> STATUS_OK in selected span of handles3874for (int i = handle; i < end; i++) {3875switch (status[i]) {3876case STATUS_UNKNOWN:3877status[i] = STATUS_OK;3878deps[i] = null;3879break;38803881case STATUS_OK:3882case STATUS_EXCEPTION:3883break;38843885default:3886throw new InternalError();3887}3888}3889}38903891/**3892* Assigns a new object to the given handle. The object previously3893* associated with the handle is forgotten. This method has no effect3894* if the given handle already has an exception associated with it.3895* This method may be called at any time after the handle is assigned.3896*/3897void setObject(int handle, Object obj) {3898switch (status[handle]) {3899case STATUS_UNKNOWN:3900case STATUS_OK:3901entries[handle] = obj;3902break;39033904case STATUS_EXCEPTION:3905break;39063907default:3908throw new InternalError();3909}3910}39113912/**3913* Looks up and returns object associated with the given handle.3914* Returns null if the given handle is NULL_HANDLE, or if it has an3915* associated ClassNotFoundException.3916*/3917Object lookupObject(int handle) {3918return (handle != NULL_HANDLE &&3919status[handle] != STATUS_EXCEPTION) ?3920entries[handle] : null;3921}39223923/**3924* Looks up and returns ClassNotFoundException associated with the3925* given handle. Returns null if the given handle is NULL_HANDLE, or3926* if there is no ClassNotFoundException associated with the handle.3927*/3928ClassNotFoundException lookupException(int handle) {3929return (handle != NULL_HANDLE &&3930status[handle] == STATUS_EXCEPTION) ?3931(ClassNotFoundException) entries[handle] : null;3932}39333934/**3935* Resets table to its initial state.3936*/3937void clear() {3938Arrays.fill(status, 0, size, (byte) 0);3939Arrays.fill(entries, 0, size, null);3940Arrays.fill(deps, 0, size, null);3941lowDep = -1;3942size = 0;3943}39443945/**3946* Returns number of handles registered in table.3947*/3948int size() {3949return size;3950}39513952/**3953* Expands capacity of internal arrays.3954*/3955private void grow() {3956int newCapacity = (entries.length << 1) + 1;39573958byte[] newStatus = new byte[newCapacity];3959Object[] newEntries = new Object[newCapacity];3960HandleList[] newDeps = new HandleList[newCapacity];39613962System.arraycopy(status, 0, newStatus, 0, size);3963System.arraycopy(entries, 0, newEntries, 0, size);3964System.arraycopy(deps, 0, newDeps, 0, size);39653966status = newStatus;3967entries = newEntries;3968deps = newDeps;3969}39703971/**3972* Simple growable list of (integer) handles.3973*/3974private static class HandleList {3975private int[] list = new int[4];3976private int size = 0;39773978public HandleList() {3979}39803981public void add(int handle) {3982if (size >= list.length) {3983int[] newList = new int[list.length << 1];3984System.arraycopy(list, 0, newList, 0, list.length);3985list = newList;3986}3987list[size++] = handle;3988}39893990public int get(int index) {3991if (index >= size) {3992throw new ArrayIndexOutOfBoundsException();3993}3994return list[index];3995}39963997public int size() {3998return size;3999}4000}4001}40024003/**4004* Method for cloning arrays in case of using unsharing reading4005*/4006private static Object cloneArray(Object array) {4007if (array instanceof Object[]) {4008return ((Object[]) array).clone();4009} else if (array instanceof boolean[]) {4010return ((boolean[]) array).clone();4011} else if (array instanceof byte[]) {4012return ((byte[]) array).clone();4013} else if (array instanceof char[]) {4014return ((char[]) array).clone();4015} else if (array instanceof double[]) {4016return ((double[]) array).clone();4017} else if (array instanceof float[]) {4018return ((float[]) array).clone();4019} else if (array instanceof int[]) {4020return ((int[]) array).clone();4021} else if (array instanceof long[]) {4022return ((long[]) array).clone();4023} else if (array instanceof short[]) {4024return ((short[]) array).clone();4025} else {4026throw new AssertionError();4027}4028}40294030private void validateDescriptor(ObjectStreamClass descriptor) {4031ObjectStreamClassValidator validating = validator;4032if (validating != null) {4033validating.validateDescriptor(descriptor);4034}4035}40364037// controlled access to ObjectStreamClassValidator4038private volatile ObjectStreamClassValidator validator;40394040private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {4041ois.validator = validator;4042}4043static {4044SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);4045SharedSecrets.setJavaObjectInputStreamReadString(ObjectInputStream::readString);4046}4047}404840494050