Source Home >> Java Source 1.6.0 >> java.io.ObjectInputStream V 0.09
  • 0001/*
  • 0002 * @(#)ObjectInputStream.java 1.175 06/04/21
  • 0003 *
  • 0004 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  • 0005 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  • 0006 */
  • 0007
  • 0008package java.io;
  • 0009
  • 0010import java.io.ObjectStreamClass.WeakClassKey;
  • 0011import java.lang.ref.ReferenceQueue;
  • 0012import java.lang.reflect.Array;
  • 0013import java.lang.reflect.Modifier;
  • 0014import java.lang.reflect.Proxy;
  • 0015import java.security.AccessControlContext;
  • 0016import java.security.AccessController;
  • 0017import java.security.PrivilegedAction;
  • 0018import java.security.PrivilegedActionException;
  • 0019import java.security.PrivilegedExceptionAction;
  • 0020import java.util.Arrays;
  • 0021import java.util.HashMap;
  • 0022import java.util.concurrent.ConcurrentHashMap;
  • 0023import java.util.concurrent.ConcurrentMap;
  • 0024import java.util.concurrent.atomic.AtomicBoolean;
  • 0025import static java.io.ObjectStreamClass.processQueue;
  • 0026
  • 0027/**
  • 0028 * An ObjectInputStream deserializes primitive data and objects previously
  • 0029 * written using an ObjectOutputStream.
  • 0030 *
  • 0031 * <p>ObjectOutputStream and ObjectInputStream can provide an application with
  • 0032 * persistent storage for graphs of objects when used with a FileOutputStream
  • 0033 * and FileInputStream respectively. ObjectInputStream is used to recover
  • 0034 * those objects previously serialized. Other uses include passing objects
  • 0035 * between hosts using a socket stream or for marshaling and unmarshaling
  • 0036 * arguments and parameters in a remote communication system.
  • 0037 *
  • 0038 * <p>ObjectInputStream ensures that the types of all objects in the graph
  • 0039 * created from the stream match the classes present in the Java Virtual
  • 0040 * Machine. Classes are loaded as required using the standard mechanisms.
  • 0041 *
  • 0042 * <p>Only objects that support the java.io.Serializable or
  • 0043 * java.io.Externalizable interface can be read from streams.
  • 0044 *
  • 0045 * <p>The method <code>readObject</code> is used to read an object from the
  • 0046 * stream. Java's safe casting should be used to get the desired type. In
  • 0047 * Java, strings and arrays are objects and are treated as objects during
  • 0048 * serialization. When read they need to be cast to the expected type.
  • 0049 *
  • 0050 * <p>Primitive data types can be read from the stream using the appropriate
  • 0051 * method on DataInput.
  • 0052 *
  • 0053 * <p>The default deserialization mechanism for objects restores the contents
  • 0054 * of each field to the value and type it had when it was written. Fields
  • 0055 * declared as transient or static are ignored by the deserialization process.
  • 0056 * References to other objects cause those objects to be read from the stream
  • 0057 * as necessary. Graphs of objects are restored correctly using a reference
  • 0058 * sharing mechanism. New objects are always allocated when deserializing,
  • 0059 * which prevents existing objects from being overwritten.
  • 0060 *
  • 0061 * <p>Reading an object is analogous to running the constructors of a new
  • 0062 * object. Memory is allocated for the object and initialized to zero (NULL).
  • 0063 * No-arg constructors are invoked for the non-serializable classes and then
  • 0064 * the fields of the serializable classes are restored from the stream starting
  • 0065 * with the serializable class closest to java.lang.object and finishing with
  • 0066 * the object's most specific class.
  • 0067 *
  • 0068 * <p>For example to read from a stream as written by the example in
  • 0069 * ObjectOutputStream:
  • 0070 * <br>
  • 0071 * <pre>
  • 0072 * FileInputStream fis = new FileInputStream("t.tmp");
  • 0073 * ObjectInputStream ois = new ObjectInputStream(fis);
  • 0074 *
  • 0075 * int i = ois.readInt();
  • 0076 * String today = (String) ois.readObject();
  • 0077 * Date date = (Date) ois.readObject();
  • 0078 *
  • 0079 * ois.close();
  • 0080 * </pre>
  • 0081 *
  • 0082 * <p>Classes control how they are serialized by implementing either the
  • 0083 * java.io.Serializable or java.io.Externalizable interfaces.
  • 0084 *
  • 0085 * <p>Implementing the Serializable interface allows object serialization to
  • 0086 * save and restore the entire state of the object and it allows classes to
  • 0087 * evolve between the time the stream is written and the time it is read. It
  • 0088 * automatically traverses references between objects, saving and restoring
  • 0089 * entire graphs.
  • 0090 *
  • 0091 * <p>Serializable classes that require special handling during the
  • 0092 * serialization and deserialization process should implement the following
  • 0093 * methods:<p>
  • 0094 *
  • 0095 * <pre>
  • 0096 * private void writeObject(java.io.ObjectOutputStream stream)
  • 0097 * throws IOException;
  • 0098 * private void readObject(java.io.ObjectInputStream stream)
  • 0099 * throws IOException, ClassNotFoundException;
  • 0100 * private void readObjectNoData()
  • 0101 * throws ObjectStreamException;
  • 0102 * </pre>
  • 0103 *
  • 0104 * <p>The readObject method is responsible for reading and restoring the state
  • 0105 * of the object for its particular class using data written to the stream by
  • 0106 * the corresponding writeObject method. The method does not need to concern
  • 0107 * itself with the state belonging to its superclasses or subclasses. State is
  • 0108 * restored by reading data from the ObjectInputStream for the individual
  • 0109 * fields and making assignments to the appropriate fields of the object.
  • 0110 * Reading primitive data types is supported by DataInput.
  • 0111 *
  • 0112 * <p>Any attempt to read object data which exceeds the boundaries of the
  • 0113 * custom data written by the corresponding writeObject method will cause an
  • 0114 * OptionalDataException to be thrown with an eof field value of true.
  • 0115 * Non-object reads which exceed the end of the allotted data will reflect the
  • 0116 * end of data in the same way that they would indicate the end of the stream:
  • 0117 * bytewise reads will return -1 as the byte read or number of bytes read, and
  • 0118 * primitive reads will throw EOFExceptions. If there is no corresponding
  • 0119 * writeObject method, then the end of default serialized data marks the end of
  • 0120 * the allotted data.
  • 0121 *
  • 0122 * <p>Primitive and object read calls issued from within a readExternal method
  • 0123 * behave in the same manner--if the stream is already positioned at the end of
  • 0124 * data written by the corresponding writeExternal method, object reads will
  • 0125 * throw OptionalDataExceptions with eof set to true, bytewise reads will
  • 0126 * return -1, and primitive reads will throw EOFExceptions. Note that this
  • 0127 * behavior does not hold for streams written with the old
  • 0128 * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
  • 0129 * end of data written by writeExternal methods is not demarcated, and hence
  • 0130 * cannot be detected.
  • 0131 *
  • 0132 * <p>The readObjectNoData method is responsible for initializing the state of
  • 0133 * the object for its particular class in the event that the serialization
  • 0134 * stream does not list the given class as a superclass of the object being
  • 0135 * deserialized. This may occur in cases where the receiving party uses a
  • 0136 * different version of the deserialized instance's class than the sending
  • 0137 * party, and the receiver's version extends classes that are not extended by
  • 0138 * the sender's version. This may also occur if the serialization stream has
  • 0139 * been tampered; hence, readObjectNoData is useful for initializing
  • 0140 * deserialized objects properly despite a "hostile" or incomplete source
  • 0141 * stream.
  • 0142 *
  • 0143 * <p>Serialization does not read or assign values to the fields of any object
  • 0144 * that does not implement the java.io.Serializable interface. Subclasses of
  • 0145 * Objects that are not serializable can be serializable. In this case the
  • 0146 * non-serializable class must have a no-arg constructor to allow its fields to
  • 0147 * be initialized. In this case it is the responsibility of the subclass to
  • 0148 * save and restore the state of the non-serializable class. It is frequently
  • 0149 * the case that the fields of that class are accessible (public, package, or
  • 0150 * protected) or that there are get and set methods that can be used to restore
  • 0151 * the state.
  • 0152 *
  • 0153 * <p>Any exception that occurs while deserializing an object will be caught by
  • 0154 * the ObjectInputStream and abort the reading process.
  • 0155 *
  • 0156 * <p>Implementing the Externalizable interface allows the object to assume
  • 0157 * complete control over the contents and format of the object's serialized
  • 0158 * form. The methods of the Externalizable interface, writeExternal and
  • 0159 * readExternal, are called to save and restore the objects state. When
  • 0160 * implemented by a class they can write and read their own state using all of
  • 0161 * the methods of ObjectOutput and ObjectInput. It is the responsibility of
  • 0162 * the objects to handle any versioning that occurs.
  • 0163 *
  • 0164 * <p>Enum constants are deserialized differently than ordinary serializable or
  • 0165 * externalizable objects. The serialized form of an enum constant consists
  • 0166 * solely of its name; field values of the constant are not transmitted. To
  • 0167 * deserialize an enum constant, ObjectInputStream reads the constant name from
  • 0168 * the stream; the deserialized constant is then obtained by calling the static
  • 0169 * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
  • 0170 * base type and the received constant name as arguments. Like other
  • 0171 * serializable or externalizable objects, enum constants can function as the
  • 0172 * targets of back references appearing subsequently in the serialization
  • 0173 * stream. The process by which enum constants are deserialized cannot be
  • 0174 * customized: any class-specific readObject, readObjectNoData, and readResolve
  • 0175 * methods defined by enum types are ignored during deserialization.
  • 0176 * Similarly, any serialPersistentFields or serialVersionUID field declarations
  • 0177 * are also ignored--all enum types have a fixed serialVersionUID of 0L.
  • 0178 *
  • 0179 * @author Mike Warres
  • 0180 * @author Roger Riggs
  • 0181 * @version 1.175, 06/04/21
  • 0182 * @see java.io.DataInput
  • 0183 * @see java.io.ObjectOutputStream
  • 0184 * @see java.io.Serializable
  • 0185 * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
  • 0186 * @since JDK1.1
  • 0187 */
  • 0188public class ObjectInputStream
  • 0189 extends InputStream implements ObjectInput, ObjectStreamConstants
  • 0190{
  • 0191 /** handle value representing null */
  • 0192 private static final int NULL_HANDLE = -1;
  • 0193
  • 0194 /** marker for unshared objects in internal handle table */
  • 0195 private static final Object unsharedMarker = new Object();
  • 0196
  • 0197 /** table mapping primitive type names to corresponding class objects */
  • 0198 private static final HashMap primClasses = new HashMap(8, 1.0F);
  • 0199 static {
  • 0200 primClasses.put("boolean", boolean.class);
  • 0201 primClasses.put("byte", byte.class);
  • 0202 primClasses.put("char", char.class);
  • 0203 primClasses.put("short", short.class);
  • 0204 primClasses.put("int", int.class);
  • 0205 primClasses.put("long", long.class);
  • 0206 primClasses.put("float", float.class);
  • 0207 primClasses.put("double", double.class);
  • 0208 primClasses.put("void", void.class);
  • 0209 }
  • 0210
  • 0211 private static class Caches {
  • 0212 /** cache of subclass security audit results */
  • 0213 static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
  • 0214 new ConcurrentHashMap<WeakClassKey,Boolean>();
  • 0215
  • 0216 /** queue for WeakReferences to audited subclasses */
  • 0217 static final ReferenceQueue<Class<?>> subclassAuditsQueue =
  • 0218 new ReferenceQueue<Class<?>>();
  • 0219 }
  • 0220
  • 0221 /** filter stream for handling block data conversion */
  • 0222 private final BlockDataInputStream bin;
  • 0223 /** validation callback list */
  • 0224 private final ValidationList vlist;
  • 0225 /** recursion depth */
  • 0226 private int depth;
  • 0227 /** whether stream is closed */
  • 0228 private boolean closed;
  • 0229
  • 0230 /** wire handle -> obj/exception map */
  • 0231 private final HandleTable handles;
  • 0232 /** scratch field for passing handle values up/down call stack */
  • 0233 private int passHandle = NULL_HANDLE;
  • 0234 /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
  • 0235 private boolean defaultDataEnd = false;
  • 0236
  • 0237 /** buffer for reading primitive field values */
  • 0238 private byte[] primVals;
  • 0239
  • 0240 /** if true, invoke readObjectOverride() instead of readObject() */
  • 0241 private final boolean enableOverride;
  • 0242 /** if true, invoke resolveObject() */
  • 0243 private boolean enableResolve;
  • 0244
  • 0245 /**
  • 0246 * Context during upcalls to class-defined readObject methods; holds
  • 0247 * object currently being deserialized and descriptor for current class.
  • 0248 * Null when not during readObject upcall.
  • 0249 */
  • 0250 private CallbackContext curContext;
  • 0251
  • 0252 /**
  • 0253 * Creates an ObjectInputStream that reads from the specified InputStream.
  • 0254 * A serialization stream header is read from the stream and verified.
  • 0255 * This constructor will block until the corresponding ObjectOutputStream
  • 0256 * has written and flushed the header.
  • 0257 *
  • 0258 * <p>If a security manager is installed, this constructor will check for
  • 0259 * the "enableSubclassImplementation" SerializablePermission when invoked
  • 0260 * directly or indirectly by the constructor of a subclass which overrides
  • 0261 * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
  • 0262 * methods.
  • 0263 *
  • 0264 * @param in input stream to read from
  • 0265 * @throws StreamCorruptedException if the stream header is incorrect
  • 0266 * @throws IOException if an I/O error occurs while reading stream header
  • 0267 * @throws SecurityException if untrusted subclass illegally overrides
  • 0268 * security-sensitive methods
  • 0269 * @throws NullPointerException if <code>in</code> is <code>null</code>
  • 0270 * @see ObjectInputStream#ObjectInputStream()
  • 0271 * @see ObjectInputStream#readFields()
  • 0272 * @see ObjectOutputStream#ObjectOutputStream(OutputStream)
  • 0273 */
  • 0274 public ObjectInputStream(InputStream in) throws IOException {
  • 0275 verifySubclass();
  • 0276 bin = new BlockDataInputStream(in);
  • 0277 handles = new HandleTable(10);
  • 0278 vlist = new ValidationList();
  • 0279 enableOverride = false;
  • 0280 readStreamHeader();
  • 0281 bin.setBlockDataMode(true);
  • 0282 }
  • 0283
  • 0284 /**
  • 0285 * Provide a way for subclasses that are completely reimplementing
  • 0286 * ObjectInputStream to not have to allocate private data just used by this
  • 0287 * implementation of ObjectInputStream.
  • 0288 *
  • 0289 * <p>If there is a security manager installed, this method first calls the
  • 0290 * security manager's <code>checkPermission</code> method with the
  • 0291 * <code>SerializablePermission("enableSubclassImplementation")</code>
  • 0292 * permission to ensure it's ok to enable subclassing.
  • 0293 *
  • 0294 * @throws SecurityException if a security manager exists and its
  • 0295 * <code>checkPermission</code> method denies enabling
  • 0296 * subclassing.
  • 0297 * @see SecurityManager#checkPermission
  • 0298 * @see java.io.SerializablePermission
  • 0299 */
  • 0300 protected ObjectInputStream() throws IOException, SecurityException {
  • 0301 SecurityManager sm = System.getSecurityManager();
  • 0302 if (sm != null) {
  • 0303 sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  • 0304 }
  • 0305 bin = null;
  • 0306 handles = null;
  • 0307 vlist = null;
  • 0308 enableOverride = true;
  • 0309 }
  • 0310
  • 0311 /**
  • 0312 * Read an object from the ObjectInputStream. The class of the object, the
  • 0313 * signature of the class, and the values of the non-transient and
  • 0314 * non-static fields of the class and all of its supertypes are read.
  • 0315 * Default deserializing for a class can be overriden using the writeObject
  • 0316 * and readObject methods. Objects referenced by this object are read
  • 0317 * transitively so that a complete equivalent graph of objects is
  • 0318 * reconstructed by readObject.
  • 0319 *
  • 0320 * <p>The root object is completely restored when all of its fields and the
  • 0321 * objects it references are completely restored. At this point the object
  • 0322 * validation callbacks are executed in order based on their registered
  • 0323 * priorities. The callbacks are registered by objects (in the readObject
  • 0324 * special methods) as they are individually restored.
  • 0325 *
  • 0326 * <p>Exceptions are thrown for problems with the InputStream and for
  • 0327 * classes that should not be deserialized. All exceptions are fatal to
  • 0328 * the InputStream and leave it in an indeterminate state; it is up to the
  • 0329 * caller to ignore or recover the stream state.
  • 0330 *
  • 0331 * @throws ClassNotFoundException Class of a serialized object cannot be
  • 0332 * found.
  • 0333 * @throws InvalidClassException Something is wrong with a class used by
  • 0334 * serialization.
  • 0335 * @throws StreamCorruptedException Control information in the
  • 0336 * stream is inconsistent.
  • 0337 * @throws OptionalDataException Primitive data was found in the
  • 0338 * stream instead of objects.
  • 0339 * @throws IOException Any of the usual Input/Output related exceptions.
  • 0340 */
  • 0341 public final Object readObject()
  • 0342 throws IOException, ClassNotFoundException
  • 0343 {
  • 0344 if (enableOverride) {
  • 0345 return readObjectOverride();
  • 0346 }
  • 0347
  • 0348 // if nested read, passHandle contains handle of enclosing object
  • 0349 int outerHandle = passHandle;
  • 0350 try {
  • 0351 Object obj = readObject0(false);
  • 0352 handles.markDependency(outerHandle, passHandle);
  • 0353 ClassNotFoundException ex = handles.lookupException(passHandle);
  • 0354 if (ex != null) {
  • 0355 throw ex;
  • 0356 }
  • 0357 if (depth == 0) {
  • 0358 vlist.doCallbacks();
  • 0359 }
  • 0360 return obj;
  • 0361 } finally {
  • 0362 passHandle = outerHandle;
  • 0363 if (closed && depth == 0) {
  • 0364 clear();
  • 0365 }
  • 0366 }
  • 0367 }
  • 0368
  • 0369 /**
  • 0370 * This method is called by trusted subclasses of ObjectOutputStream that
  • 0371 * constructed ObjectOutputStream using the protected no-arg constructor.
  • 0372 * The subclass is expected to provide an override method with the modifier
  • 0373 * "final".
  • 0374 *
  • 0375 * @return the Object read from the stream.
  • 0376 * @throws ClassNotFoundException Class definition of a serialized object
  • 0377 * cannot be found.
  • 0378 * @throws OptionalDataException Primitive data was found in the stream
  • 0379 * instead of objects.
  • 0380 * @throws IOException if I/O errors occurred while reading from the
  • 0381 * underlying stream
  • 0382 * @see #ObjectInputStream()
  • 0383 * @see #readObject()
  • 0384 * @since 1.2
  • 0385 */
  • 0386 protected Object readObjectOverride()
  • 0387 throws IOException, ClassNotFoundException
  • 0388 {
  • 0389 return null;
  • 0390 }
  • 0391
  • 0392 /**
  • 0393 * Reads an "unshared" object from the ObjectInputStream. This method is
  • 0394 * identical to readObject, except that it prevents subsequent calls to
  • 0395 * readObject and readUnshared from returning additional references to the
  • 0396 * deserialized instance obtained via this call. Specifically:
  • 0397 * <ul>
  • 0398 * <li>If readUnshared is called to deserialize a back-reference (the
  • 0399 * stream representation of an object which has been written
  • 0400 * previously to the stream), an ObjectStreamException will be
  • 0401 * thrown.
  • 0402 *
  • 0403 * <li>If readUnshared returns successfully, then any subsequent attempts
  • 0404 * to deserialize back-references to the stream handle deserialized
  • 0405 * by readUnshared will cause an ObjectStreamException to be thrown.
  • 0406 * </ul>
  • 0407 * Deserializing an object via readUnshared invalidates the stream handle
  • 0408 * associated with the returned object. Note that this in itself does not
  • 0409 * always guarantee that the reference returned by readUnshared is unique;
  • 0410 * the deserialized object may define a readResolve method which returns an
  • 0411 * object visible to other parties, or readUnshared may return a Class
  • 0412 * object or enum constant obtainable elsewhere in the stream or through
  • 0413 * external means. If the deserialized object defines a readResolve method
  • 0414 * and the invocation of that method returns an array, then readUnshared
  • 0415 * returns a shallow clone of that array; this guarantees that the returned
  • 0416 * array object is unique and cannot be obtained a second time from an
  • 0417 * invocation of readObject or readUnshared on the ObjectInputStream,
  • 0418 * even if the underlying data stream has been manipulated.
  • 0419 *
  • 0420 * <p>ObjectInputStream subclasses which override this method can only be
  • 0421 * constructed in security contexts possessing the
  • 0422 * "enableSubclassImplementation" SerializablePermission; any attempt to
  • 0423 * instantiate such a subclass without this permission will cause a
  • 0424 * SecurityException to be thrown.
  • 0425 *
  • 0426 * @return reference to deserialized object
  • 0427 * @throws ClassNotFoundException if class of an object to deserialize
  • 0428 * cannot be found
  • 0429 * @throws StreamCorruptedException if control information in the stream
  • 0430 * is inconsistent
  • 0431 * @throws ObjectStreamException if object to deserialize has already
  • 0432 * appeared in stream
  • 0433 * @throws OptionalDataException if primitive data is next in stream
  • 0434 * @throws IOException if an I/O error occurs during deserialization
  • 0435 * @since 1.4
  • 0436 */
  • 0437 public Object readUnshared() throws IOException, ClassNotFoundException {
  • 0438 // if nested read, passHandle contains handle of enclosing object
  • 0439 int outerHandle = passHandle;
  • 0440 try {
  • 0441 Object obj = readObject0(true);
  • 0442 handles.markDependency(outerHandle, passHandle);
  • 0443 ClassNotFoundException ex = handles.lookupException(passHandle);
  • 0444 if (ex != null) {
  • 0445 throw ex;
  • 0446 }
  • 0447 if (depth == 0) {
  • 0448 vlist.doCallbacks();
  • 0449 }
  • 0450 return obj;
  • 0451 } finally {
  • 0452 passHandle = outerHandle;
  • 0453 if (closed && depth == 0) {
  • 0454 clear();
  • 0455 }
  • 0456 }
  • 0457 }
  • 0458
  • 0459 /**
  • 0460 * Read the non-static and non-transient fields of the current class from
  • 0461 * this stream. This may only be called from the readObject method of the
  • 0462 * class being deserialized. It will throw the NotActiveException if it is
  • 0463 * called otherwise.
  • 0464 *
  • 0465 * @throws ClassNotFoundException if the class of a serialized object
  • 0466 * could not be found.
  • 0467 * @throws IOException if an I/O error occurs.
  • 0468 * @throws NotActiveException if the stream is not currently reading
  • 0469 * objects.
  • 0470 */
  • 0471 public void defaultReadObject()
  • 0472 throws IOException, ClassNotFoundException
  • 0473 {
  • 0474 if (curContext == null) {
  • 0475 throw new NotActiveException("not in call to readObject");
  • 0476 }
  • 0477 Object curObj = curContext.getObj();
  • 0478 ObjectStreamClass curDesc = curContext.getDesc();
  • 0479 bin.setBlockDataMode(false);
  • 0480 defaultReadFields(curObj, curDesc);
  • 0481 bin.setBlockDataMode(true);
  • 0482 if (!curDesc.hasWriteObjectData()) {
  • 0483 /*
  • 0484 * Fix for 4360508: since stream does not contain terminating
  • 0485 * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
  • 0486 * knows to simulate end-of-custom-data behavior.
  • 0487 */
  • 0488 defaultDataEnd = true;
  • 0489 }
  • 0490 ClassNotFoundException ex = handles.lookupException(passHandle);
  • 0491 if (ex != null) {
  • 0492 throw ex;
  • 0493 }
  • 0494 }
  • 0495
  • 0496 /**
  • 0497 * Reads the persistent fields from the stream and makes them available by
  • 0498 * name.
  • 0499 *
  • 0500 * @return the <code>GetField</code> object representing the persistent
  • 0501 * fields of the object being deserialized
  • 0502 * @throws ClassNotFoundException if the class of a serialized object
  • 0503 * could not be found.
  • 0504 * @throws IOException if an I/O error occurs.
  • 0505 * @throws NotActiveException if the stream is not currently reading
  • 0506 * objects.
  • 0507 * @since 1.2
  • 0508 */
  • 0509 public ObjectInputStream.GetField readFields()
  • 0510 throws IOException, ClassNotFoundException
  • 0511 {
  • 0512 if (curContext == null) {
  • 0513 throw new NotActiveException("not in call to readObject");
  • 0514 }
  • 0515 Object curObj = curContext.getObj();
  • 0516 ObjectStreamClass curDesc = curContext.getDesc();
  • 0517 bin.setBlockDataMode(false);
  • 0518 GetFieldImpl getField = new GetFieldImpl(curDesc);
  • 0519 getField.readFields();
  • 0520 bin.setBlockDataMode(true);
  • 0521 if (!curDesc.hasWriteObjectData()) {
  • 0522 /*
  • 0523 * Fix for 4360508: since stream does not contain terminating
  • 0524 * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
  • 0525 * knows to simulate end-of-custom-data behavior.
  • 0526 */
  • 0527 defaultDataEnd = true;
  • 0528 }
  • 0529
  • 0530 return getField;
  • 0531 }
  • 0532
  • 0533 /**
  • 0534 * Register an object to be validated before the graph is returned. While
  • 0535 * similar to resolveObject these validations are called after the entire
  • 0536 * graph has been reconstituted. Typically, a readObject method will
  • 0537 * register the object with the stream so that when all of the objects are
  • 0538 * restored a final set of validations can be performed.
  • 0539 *
  • 0540 * @param obj the object to receive the validation callback.
  • 0541 * @param prio controls the order of callbacks;zero is a good default.
  • 0542 * Use higher numbers to be called back earlier, lower numbers for
  • 0543 * later callbacks. Within a priority, callbacks are processed in
  • 0544 * no particular order.
  • 0545 * @throws NotActiveException The stream is not currently reading objects
  • 0546 * so it is invalid to register a callback.
  • 0547 * @throws InvalidObjectException The validation object is null.
  • 0548 */
  • 0549 public void registerValidation(ObjectInputValidation obj, int prio)
  • 0550 throws NotActiveException, InvalidObjectException
  • 0551 {
  • 0552 if (depth == 0) {
  • 0553 throw new NotActiveException("stream inactive");
  • 0554 }
  • 0555 vlist.register(obj, prio);
  • 0556 }
  • 0557
  • 0558 /**
  • 0559 * Load the local class equivalent of the specified stream class
  • 0560 * description. Subclasses may implement this method to allow classes to
  • 0561 * be fetched from an alternate source.
  • 0562 *
  • 0563 * <p>The corresponding method in <code>ObjectOutputStream</code> is
  • 0564 * <code>annotateClass</code>. This method will be invoked only once for
  • 0565 * each unique class in the stream. This method can be implemented by
  • 0566 * subclasses to use an alternate loading mechanism but must return a
  • 0567 * <code>Class</code> object. Once returned, if the class is not an array
  • 0568 * class, its serialVersionUID is compared to the serialVersionUID of the
  • 0569 * serialized class, and if there is a mismatch, the deserialization fails
  • 0570 * and an {@link InvalidClassException} is thrown.
  • 0571 *
  • 0572 * <p>The default implementation of this method in
  • 0573 * <code>ObjectInputStream</code> returns the result of calling
  • 0574 * <pre>
  • 0575 * Class.forName(desc.getName(), false, loader)
  • 0576 * </pre>
  • 0577 * where <code>loader</code> is determined as follows: if there is a
  • 0578 * method on the current thread's stack whose declaring class was
  • 0579 * defined by a user-defined class loader (and was not a generated to
  • 0580 * implement reflective invocations), then <code>loader</code> is class
  • 0581 * loader corresponding to the closest such method to the currently
  • 0582 * executing frame; otherwise, <code>loader</code> is
  • 0583 * <code>null</code>. If this call results in a
  • 0584 * <code>ClassNotFoundException</code> and the name of the passed
  • 0585 * <code>ObjectStreamClass</code> instance is the Java language keyword
  • 0586 * for a primitive type or void, then the <code>Class</code> object
  • 0587 * representing that primitive type or void will be returned
  • 0588 * (e.g., an <code>ObjectStreamClass</code> with the name
  • 0589 * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
  • 0590 * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
  • 0591 * the caller of this method.
  • 0592 *
  • 0593 * @param desc an instance of class <code>ObjectStreamClass</code>
  • 0594 * @return a <code>Class</code> object corresponding to <code>desc</code>
  • 0595 * @throws IOException any of the usual Input/Output exceptions.
  • 0596 * @throws ClassNotFoundException if class of a serialized object cannot
  • 0597 * be found.
  • 0598 */
  • 0599 protected Class<?> resolveClass(ObjectStreamClass desc)
  • 0600 throws IOException, ClassNotFoundException
  • 0601 {
  • 0602 String name = desc.getName();
  • 0603 try {
  • 0604 return Class.forName(name, false, latestUserDefinedLoader());
  • 0605 } catch (ClassNotFoundException ex) {
  • 0606 Class cl = (Class) primClasses.get(name);
  • 0607 if (cl != null) {
  • 0608 return cl;
  • 0609 } else {
  • 0610 throw ex;
  • 0611 }
  • 0612 }
  • 0613 }
  • 0614
  • 0615 /**
  • 0616 * Returns a proxy class that implements the interfaces named in a proxy
  • 0617 * class descriptor; subclasses may implement this method to read custom
  • 0618 * data from the stream along with the descriptors for dynamic proxy
  • 0619 * classes, allowing them to use an alternate loading mechanism for the
  • 0620 * interfaces and the proxy class.
  • 0621 *
  • 0622 * <p>This method is called exactly once for each unique proxy class
  • 0623 * descriptor in the stream.
  • 0624 *
  • 0625 * <p>The corresponding method in <code>ObjectOutputStream</code> is
  • 0626 * <code>annotateProxyClass</code>. For a given subclass of
  • 0627 * <code>ObjectInputStream</code> that overrides this method, the
  • 0628 * <code>annotateProxyClass</code> method in the corresponding subclass of
  • 0629 * <code>ObjectOutputStream</code> must write any data or objects read by
  • 0630 * this method.
  • 0631 *
  • 0632 * <p>The default implementation of this method in
  • 0633 * <code>ObjectInputStream</code> returns the result of calling
  • 0634 * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
  • 0635 * objects for the interfaces that are named in the <code>interfaces</code>
  • 0636 * parameter. The <code>Class</code> object for each interface name
  • 0637 * <code>i</code> is the value returned by calling
  • 0638 * <pre>
  • 0639 * Class.forName(i, false, loader)
  • 0640 * </pre>
  • 0641 * where <code>loader</code> is that of the first non-<code>null</code>
  • 0642 * class loader up the execution stack, or <code>null</code> if no
  • 0643 * non-<code>null</code> class loaders are on the stack (the same class
  • 0644 * loader choice used by the <code>resolveClass</code> method). Unless any
  • 0645 * of the resolved interfaces are non-public, this same value of
  • 0646 * <code>loader</code> is also the class loader passed to
  • 0647 * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
  • 0648 * their class loader is passed instead (if more than one non-public
  • 0649 * interface class loader is encountered, an
  • 0650 * <code>IllegalAccessError</code> is thrown).
  • 0651 * If <code>Proxy.getProxyClass</code> throws an
  • 0652 * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
  • 0653 * will throw a <code>ClassNotFoundException</code> containing the
  • 0654 * <code>IllegalArgumentException</code>.
  • 0655 *
  • 0656 * @param interfaces the list of interface names that were
  • 0657 * deserialized in the proxy class descriptor
  • 0658 * @return a proxy class for the specified interfaces
  • 0659 * @throws IOException any exception thrown by the underlying
  • 0660 * <code>InputStream</code>
  • 0661 * @throws ClassNotFoundException if the proxy class or any of the
  • 0662 * named interfaces could not be found
  • 0663 * @see ObjectOutputStream#annotateProxyClass(Class)
  • 0664 * @since 1.3
  • 0665 */
  • 0666 protected Class<?> resolveProxyClass(String[] interfaces)
  • 0667 throws IOException, ClassNotFoundException
  • 0668 {
  • 0669 ClassLoader latestLoader = latestUserDefinedLoader();
  • 0670 ClassLoader nonPublicLoader = null;
  • 0671 boolean hasNonPublicInterface = false;
  • 0672
  • 0673 // define proxy in class loader of non-public interface(s), if any
  • 0674 Class[] classObjs = new Class[interfaces.length];
  • 0675 for (int i = 0; i < interfaces.length; i++) {
  • 0676 Class cl = Class.forName(interfaces[i], false, latestLoader);
  • 0677 if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
  • 0678 if (hasNonPublicInterface) {
  • 0679 if (nonPublicLoader != cl.getClassLoader()) {
  • 0680 throw new IllegalAccessError(
  • 0681 "conflicting non-public interface class loaders");
  • 0682 }
  • 0683 } else {
  • 0684 nonPublicLoader = cl.getClassLoader();
  • 0685 hasNonPublicInterface = true;
  • 0686 }
  • 0687 }
  • 0688 classObjs[i] = cl;
  • 0689 }
  • 0690 try {
  • 0691 return Proxy.getProxyClass(
  • 0692 hasNonPublicInterface ? nonPublicLoader : latestLoader,
  • 0693 classObjs);
  • 0694 } catch (IllegalArgumentException e) {
  • 0695 throw new ClassNotFoundException(null, e);
  • 0696 }
  • 0697 }
  • 0698
  • 0699 /**
  • 0700 * This method will allow trusted subclasses of ObjectInputStream to
  • 0701 * substitute one object for another during deserialization. Replacing
  • 0702 * objects is disabled until enableResolveObject is called. The
  • 0703 * enableResolveObject method checks that the stream requesting to resolve
  • 0704 * object can be trusted. Every reference to serializable objects is passed
  • 0705 * to resolveObject. To insure that the private state of objects is not
  • 0706 * unintentionally exposed only trusted streams may use resolveObject.
  • 0707 *
  • 0708 * <p>This method is called after an object has been read but before it is
  • 0709 * returned from readObject. The default resolveObject method just returns
  • 0710 * the same object.
  • 0711 *
  • 0712 * <p>When a subclass is replacing objects it must insure that the
  • 0713 * substituted object is compatible with every field where the reference
  • 0714 * will be stored. Objects whose type is not a subclass of the type of the
  • 0715 * field or array element abort the serialization by raising an exception
  • 0716 * and the object is not be stored.
  • 0717 *
  • 0718 * <p>This method is called only once when each object is first
  • 0719 * encountered. All subsequent references to the object will be redirected
  • 0720 * to the new object.
  • 0721 *
  • 0722 * @param obj object to be substituted
  • 0723 * @return the substituted object
  • 0724 * @throws IOException Any of the usual Input/Output exceptions.
  • 0725 */
  • 0726 protected Object resolveObject(Object obj) throws IOException {
  • 0727 return obj;
  • 0728 }
  • 0729
  • 0730 /**
  • 0731 * Enable the stream to allow objects read from the stream to be replaced.
  • 0732 * When enabled, the resolveObject method is called for every object being
  • 0733 * deserialized.
  • 0734 *
  • 0735 * <p>If <i>enable</i> is true, and there is a security manager installed,
  • 0736 * this method first calls the security manager's
  • 0737 * <code>checkPermission</code> method with the
  • 0738 * <code>SerializablePermission("enableSubstitution")</code> permission to
  • 0739 * ensure it's ok to enable the stream to allow objects read from the
  • 0740 * stream to be replaced.
  • 0741 *
  • 0742 * @param enable true for enabling use of <code>resolveObject</code> for
  • 0743 * every object being deserialized
  • 0744 * @return the previous setting before this method was invoked
  • 0745 * @throws SecurityException if a security manager exists and its
  • 0746 * <code>checkPermission</code> method denies enabling the stream
  • 0747 * to allow objects read from the stream to be replaced.
  • 0748 * @see SecurityManager#checkPermission
  • 0749 * @see java.io.SerializablePermission
  • 0750 */
  • 0751 protected boolean enableResolveObject(boolean enable)
  • 0752 throws SecurityException
  • 0753 {
  • 0754 if (enable == enableResolve) {
  • 0755 return enable;
  • 0756 }
  • 0757 if (enable) {
  • 0758 SecurityManager sm = System.getSecurityManager();
  • 0759 if (sm != null) {
  • 0760 sm.checkPermission(SUBSTITUTION_PERMISSION);
  • 0761 }
  • 0762 }
  • 0763 enableResolve = enable;
  • 0764 return !enableResolve;
  • 0765 }
  • 0766
  • 0767 /**
  • 0768 * The readStreamHeader method is provided to allow subclasses to read and
  • 0769 * verify their own stream headers. It reads and verifies the magic number
  • 0770 * and version number.
  • 0771 *
  • 0772 * @throws IOException if there are I/O errors while reading from the
  • 0773 * underlying <code>InputStream</code>
  • 0774 * @throws StreamCorruptedException if control information in the stream
  • 0775 * is inconsistent
  • 0776 */
  • 0777 protected void readStreamHeader()
  • 0778 throws IOException, StreamCorruptedException
  • 0779 {
  • 0780 short s0 = bin.readShort();
  • 0781 short s1 = bin.readShort();
  • 0782 if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
  • 0783 throw new StreamCorruptedException(
  • 0784 String.format("invalid stream header: %04X%04X", s0, s1));
  • 0785 }
  • 0786 }
  • 0787
  • 0788 /**
  • 0789 * Read a class descriptor from the serialization stream. This method is
  • 0790 * called when the ObjectInputStream expects a class descriptor as the next
  • 0791 * item in the serialization stream. Subclasses of ObjectInputStream may
  • 0792 * override this method to read in class descriptors that have been written
  • 0793 * in non-standard formats (by subclasses of ObjectOutputStream which have
  • 0794 * overridden the <code>writeClassDescriptor</code> method). By default,
  • 0795 * this method reads class descriptors according to the format defined in
  • 0796 * the Object Serialization specification.
  • 0797 *
  • 0798 * @return the class descriptor read
  • 0799 * @throws IOException If an I/O error has occurred.
  • 0800 * @throws ClassNotFoundException If the Class of a serialized object used
  • 0801 * in the class descriptor representation cannot be found
  • 0802 * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
  • 0803 * @since 1.3
  • 0804 */
  • 0805 protected ObjectStreamClass readClassDescriptor()
  • 0806 throws IOException, ClassNotFoundException
  • 0807 {
  • 0808 ObjectStreamClass desc = new ObjectStreamClass();
  • 0809 desc.readNonProxy(this);
  • 0810 return desc;
  • 0811 }
  • 0812
  • 0813 /**
  • 0814 * Reads a byte of data. This method will block if no input is available.
  • 0815 *
  • 0816 * @return the byte read, or -1 if the end of the stream is reached.
  • 0817 * @throws IOException If an I/O error has occurred.
  • 0818 */
  • 0819 public int read() throws IOException {
  • 0820 return bin.read();
  • 0821 }
  • 0822
  • 0823 /**
  • 0824 * Reads into an array of bytes. This method will block until some input
  • 0825 * is available. Consider using java.io.DataInputStream.readFully to read
  • 0826 * exactly 'length' bytes.
  • 0827 *
  • 0828 * @param buf the buffer into which the data is read
  • 0829 * @param off the start offset of the data
  • 0830 * @param len the maximum number of bytes read
  • 0831 * @return the actual number of bytes read, -1 is returned when the end of
  • 0832 * the stream is reached.
  • 0833 * @throws IOException If an I/O error has occurred.
  • 0834 * @see java.io.DataInputStream#readFully(byte[],int,int)
  • 0835 */
  • 0836 public int read(byte[] buf, int off, int len) throws IOException {
  • 0837 if (buf == null) {
  • 0838 throw new NullPointerException();
  • 0839 }
  • 0840 int endoff = off + len;
  • 0841 if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
  • 0842 throw new IndexOutOfBoundsException();
  • 0843 }
  • 0844 return bin.read(buf, off, len, false);
  • 0845 }
  • 0846
  • 0847 /**
  • 0848 * Returns the number of bytes that can be read without blocking.
  • 0849 *
  • 0850 * @return the number of available bytes.
  • 0851 * @throws IOException if there are I/O errors while reading from the
  • 0852 * underlying <code>InputStream</code>
  • 0853 */
  • 0854 public int available() throws IOException {
  • 0855 return bin.available();
  • 0856 }
  • 0857
  • 0858 /**
  • 0859 * Closes the input stream. Must be called to release any resources
  • 0860 * associated with the stream.
  • 0861 *
  • 0862 * @throws IOException If an I/O error has occurred.
  • 0863 */
  • 0864 public void close() throws IOException {
  • 0865 /*
  • 0866 * Even if stream already closed, propagate redundant close to
  • 0867 * underlying stream to stay consistent with previous implementations.
  • 0868 */
  • 0869 closed = true;
  • 0870 if (depth == 0) {
  • 0871 clear();
  • 0872 }
  • 0873 bin.close();
  • 0874 }
  • 0875
  • 0876 /**
  • 0877 * Reads in a boolean.
  • 0878 *
  • 0879 * @return the boolean read.
  • 0880 * @throws EOFException If end of file is reached.
  • 0881 * @throws IOException If other I/O error has occurred.
  • 0882 */
  • 0883 public boolean readBoolean() throws IOException {
  • 0884 return bin.readBoolean();
  • 0885 }
  • 0886
  • 0887 /**
  • 0888 * Reads an 8 bit byte.
  • 0889 *
  • 0890 * @return the 8 bit byte read.
  • 0891 * @throws EOFException If end of file is reached.
  • 0892 * @throws IOException If other I/O error has occurred.
  • 0893 */
  • 0894 public byte readByte() throws IOException {
  • 0895 return bin.readByte();
  • 0896 }
  • 0897
  • 0898 /**
  • 0899 * Reads an unsigned 8 bit byte.
  • 0900 *
  • 0901 * @return the 8 bit byte read.
  • 0902 * @throws EOFException If end of file is reached.
  • 0903 * @throws IOException If other I/O error has occurred.
  • 0904 */
  • 0905 public int readUnsignedByte() throws IOException {
  • 0906 return bin.readUnsignedByte();
  • 0907 }
  • 0908
  • 0909 /**
  • 0910 * Reads a 16 bit char.
  • 0911 *
  • 0912 * @return the 16 bit char read.
  • 0913 * @throws EOFException If end of file is reached.
  • 0914 * @throws IOException If other I/O error has occurred.
  • 0915 */
  • 0916 public char readChar() throws IOException {
  • 0917 return bin.readChar();
  • 0918 }
  • 0919
  • 0920 /**
  • 0921 * Reads a 16 bit short.
  • 0922 *
  • 0923 * @return the 16 bit short read.
  • 0924 * @throws EOFException If end of file is reached.
  • 0925 * @throws IOException If other I/O error has occurred.
  • 0926 */
  • 0927 public short readShort() throws IOException {
  • 0928 return bin.readShort();
  • 0929 }
  • 0930
  • 0931 /**
  • 0932 * Reads an unsigned 16 bit short.
  • 0933 *
  • 0934 * @return the 16 bit short read.
  • 0935 * @throws EOFException If end of file is reached.
  • 0936 * @throws IOException If other I/O error has occurred.
  • 0937 */
  • 0938 public int readUnsignedShort() throws IOException {
  • 0939 return bin.readUnsignedShort();
  • 0940 }
  • 0941
  • 0942 /**
  • 0943 * Reads a 32 bit int.
  • 0944 *
  • 0945 * @return the 32 bit integer read.
  • 0946 * @throws EOFException If end of file is reached.
  • 0947 * @throws IOException If other I/O error has occurred.
  • 0948 */
  • 0949 public int readInt() throws IOException {
  • 0950 return bin.readInt();
  • 0951 }
  • 0952
  • 0953 /**
  • 0954 * Reads a 64 bit long.
  • 0955 *
  • 0956 * @return the read 64 bit long.
  • 0957 * @throws EOFException If end of file is reached.
  • 0958 * @throws IOException If other I/O error has occurred.
  • 0959 */
  • 0960 public long readLong() throws IOException {
  • 0961 return bin.readLong();
  • 0962 }
  • 0963
  • 0964 /**
  • 0965 * Reads a 32 bit float.
  • 0966 *
  • 0967 * @return the 32 bit float read.
  • 0968 * @throws EOFException If end of file is reached.
  • 0969 * @throws IOException If other I/O error has occurred.
  • 0970 */
  • 0971 public float readFloat() throws IOException {
  • 0972 return bin.readFloat();
  • 0973 }
  • 0974
  • 0975 /**
  • 0976 * Reads a 64 bit double.
  • 0977 *
  • 0978 * @return the 64 bit double read.
  • 0979 * @throws EOFException If end of file is reached.
  • 0980 * @throws IOException If other I/O error has occurred.
  • 0981 */
  • 0982 public double readDouble() throws IOException {
  • 0983 return bin.readDouble();
  • 0984 }
  • 0985
  • 0986 /**
  • 0987 * Reads bytes, blocking until all bytes are read.
  • 0988 *
  • 0989 * @param buf the buffer into which the data is read
  • 0990 * @throws EOFException If end of file is reached.
  • 0991 * @throws IOException If other I/O error has occurred.
  • 0992 */
  • 0993 public void readFully(byte[] buf) throws IOException {
  • 0994 bin.readFully(buf, 0, buf.length, false);
  • 0995 }
  • 0996
  • 0997 /**
  • 0998 * Reads bytes, blocking until all bytes are read.
  • 0999 *
  • 1000 * @param buf the buffer into which the data is read
  • 1001 * @param off the start offset of the data
  • 1002 * @param len the maximum number of bytes to read
  • 1003 * @throws EOFException If end of file is reached.
  • 1004 * @throws IOException If other I/O error has occurred.
  • 1005 */
  • 1006 public void readFully(byte[] buf, int off, int len) throws IOException {
  • 1007 int endoff = off + len;
  • 1008 if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
  • 1009 throw new IndexOutOfBoundsException();
  • 1010 }
  • 1011 bin.readFully(buf, off, len, false);
  • 1012 }
  • 1013
  • 1014 /**
  • 1015 * Skips bytes.
  • 1016 *
  • 1017 * @param len the number of bytes to be skipped
  • 1018 * @return the actual number of bytes skipped.
  • 1019 * @throws IOException If an I/O error has occurred.
  • 1020 */
  • 1021 public int skipBytes(int len) throws IOException {
  • 1022 return bin.skipBytes(len);
  • 1023 }
  • 1024
  • 1025 /**
  • 1026 * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
  • 1027 *
  • 1028 * @return a String copy of the line.
  • 1029 * @throws IOException if there are I/O errors while reading from the
  • 1030 * underlying <code>InputStream</code>
  • 1031 * @deprecated This method does not properly convert bytes to characters.
  • 1032 * see DataInputStream for the details and alternatives.
  • 1033 */
  • 1034 @Deprecated
  • 1035 public String readLine() throws IOException {
  • 1036 return bin.readLine();
  • 1037 }
  • 1038
  • 1039 /**
  • 1040 * Reads a String in
  • 1041 * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
  • 1042 * format.
  • 1043 *
  • 1044 * @return the String.
  • 1045 * @throws IOException if there are I/O errors while reading from the
  • 1046 * underlying <code>InputStream</code>
  • 1047 * @throws UTFDataFormatException if read bytes do not represent a valid
  • 1048 * modified UTF-8 encoding of a string
  • 1049 */
  • 1050 public String readUTF() throws IOException {
  • 1051 return bin.readUTF();
  • 1052 }
  • 1053
  • 1054 /**
  • 1055 * Provide access to the persistent fields read from the input stream.
  • 1056 */
  • 1057 public static abstract class GetField {
  • 1058
  • 1059 /**
  • 1060 * Get the ObjectStreamClass that describes the fields in the stream.
  • 1061 *
  • 1062 * @return the descriptor class that describes the serializable fields
  • 1063 */
  • 1064 public abstract ObjectStreamClass getObjectStreamClass();
  • 1065
  • 1066 /**
  • 1067 * Return true if the named field is defaulted and has no value in this
  • 1068 * stream.
  • 1069 *
  • 1070 * @param name the name of the field
  • 1071 * @return true, if and only if the named field is defaulted
  • 1072 * @throws IOException if there are I/O errors while reading from
  • 1073 * the underlying <code>InputStream</code>
  • 1074 * @throws IllegalArgumentException if <code>name</code> does not
  • 1075 * correspond to a serializable field
  • 1076 */
  • 1077 public abstract boolean defaulted(String name) throws IOException;
  • 1078
  • 1079 /**
  • 1080 * Get the value of the named boolean field from the persistent field.
  • 1081 *
  • 1082 * @param name the name of the field
  • 1083 * @param val the default value to use if <code>name</code> does not
  • 1084 * have a value
  • 1085 * @return the value of the named <code>boolean</code> field
  • 1086 * @throws IOException if there are I/O errors while reading from the
  • 1087 * underlying <code>InputStream</code>
  • 1088 * @throws IllegalArgumentException if type of <code>name</code> is
  • 1089 * not serializable or if the field type is incorrect
  • 1090 */
  • 1091 public abstract boolean get(String name, boolean val)
  • 1092 throws IOException;
  • 1093
  • 1094 /**
  • 1095 * Get the value of the named byte field from the persistent field.
  • 1096 *
  • 1097 * @param name the name of the field
  • 1098 * @param val the default value to use if <code>name</code> does not
  • 1099 * have a value
  • 1100 * @return the value of the named <code>byte</code> field
  • 1101 * @throws IOException if there are I/O errors while reading from the
  • 1102 * underlying <code>InputStream</code>
  • 1103 * @throws IllegalArgumentException if type of <code>name</code> is
  • 1104 * not serializable or if the field type is incorrect
  • 1105 */
  • 1106 public abstract byte get(String name, byte val) throws IOException;
  • 1107
  • 1108 /**
  • 1109 * Get the value of the named char field from the persistent field.
  • 1110 *
  • 1111 * @param name the name of the field
  • 1112 * @param val the default value to use if <code>name</code> does not
  • 1113 * have a value
  • 1114 * @return the value of the named <code>char</code> field
  • 1115 * @throws IOException if there are I/O errors while reading from the
  • 1116 * underlying <code>InputStream</code>
  • 1117 * @throws IllegalArgumentException if type of <code>name</code> is
  • 1118 * not serializable or if the field type is incorrect
  • 1119 */
  • 1120 public abstract char get(String name, char val) throws IOException;
  • 1121
  • 1122 /**
  • 1123 * Get the value of the named short field from the persistent field.
  • 1124 *
  • 1125 * @param name the name of the field
  • 1126 * @param val the default value to use if <code>name</code> does not
  • 1127 * have a value
  • 1128 * @return the value of the named <code>short</code> field
  • 1129 * @throws IOException if there are I/O errors while reading from the
  • 1130 * underlying <code>InputStream</code>
  • 1131 * @throws IllegalArgumentException if type of <code>name</code> is
  • 1132 * not serializable or if the field type is incorrect
  • 1133 */
  • 1134 public abstract short get(String name, short val) throws IOException;
  • 1135
  • 1136 /**
  • 1137 * Get the value of the named int field from the persistent field.
  • 1138 *
  • 1139 * @param name the name of the field
  • 1140 * @param val the default value to use if <code>name</code> does not
  • 1141 * have a value
  • 1142 * @return the value of the named <code>int</code> field
  • 1143 * @throws IOException if there are I/O errors while reading from the
  • 1144 * underlying <code>InputStream</code>
  • 1145 * @throws IllegalArgumentException if type of <code>name</code> is
  • 1146 * not serializable or if the field type is incorrect
  • 1147 */
  • 1148 public abstract int get(String name, int val) throws IOException;
  • 1149
  • 1150 /**
  • 1151 * Get the value of the named long field from the persistent field.
  • 1152 *
  • 1153 * @param name the name of the field
  • 1154 * @param val the default value to use if <code>name</code> does not
  • 1155 * have a value
  • 1156 * @return the value of the named <code>long</code> field
  • 1157 * @throws IOException if there are I/O errors while reading from the
  • 1158 * underlying <code>InputStream</code>
  • 1159 * @throws IllegalArgumentException if type of <code>name</code> is
  • 1160 * not serializable or if the field type is incorrect
  • 1161 */
  • 1162 public abstract long get(String name, long val) throws IOException;
  • 1163
  • 1164 /**
  • 1165 * Get the value of the named float field from the persistent field.
  • 1166 *
  • 1167 * @param name the name of the field
  • 1168 * @param val the default value to use if <code>name</code> does not
  • 1169 * have a value
  • 1170 * @return the value of the named <code>float</code> field
  • 1171 * @throws IOException if there are I/O errors while reading from the
  • 1172 * underlying <code>InputStream</code>
  • 1173 * @throws IllegalArgumentException if type of <code>name</code> is
  • 1174 * not serializable or if the field type is incorrect
  • 1175 */
  • 1176 public abstract float get(String name, float val) throws IOException;
  • 1177
  • 1178 /**
  • 1179 * Get the value of the named double field from the persistent field.
  • 1180 *
  • 1181 * @param name the name of the field
  • 1182 * @param val the default value to use if <code>name</code> does not
  • 1183 * have a value
  • 1184 * @return the value of the named <code>double</code> field
  • 1185 * @throws IOException if there are I/O errors while reading from the
  • 1186 * underlying <code>InputStream</code>
  • 1187 * @throws IllegalArgumentException if type of <code>name</code> is
  • 1188 * not serializable or if the field type is incorrect
  • 1189 */
  • 1190 public abstract double get(String name, double val) throws IOException;
  • 1191
  • 1192 /**
  • 1193 * Get the value of the named Object field from the persistent field.
  • 1194 *
  • 1195 * @param name the name of the field
  • 1196 * @param val the default value to use if <code>name</code> does not
  • 1197 * have a value
  • 1198 * @return the value of the named <code>Object</code> field
  • 1199 * @throws IOException if there are I/O errors while reading from the
  • 1200 * underlying <code>InputStream</code>
  • 1201 * @throws IllegalArgumentException if type of <code>name</code> is
  • 1202 * not serializable or if the field type is incorrect
  • 1203 */
  • 1204 public abstract Object get(String name, Object val) throws IOException;
  • 1205 }
  • 1206
  • 1207 /**
  • 1208 * Verifies that this (possibly subclass) instance can be constructed
  • 1209 * without violating security constraints: the subclass must not override
  • 1210 * security-sensitive non-final methods, or else the
  • 1211 * "enableSubclassImplementation" SerializablePermission is checked.
  • 1212 */
  • 1213 private void verifySubclass() {
  • 1214 Class cl = getClass();
  • 1215 if (cl == ObjectInputStream.class) {
  • 1216 return;
  • 1217 }
  • 1218 SecurityManager sm = System.getSecurityManager();
  • 1219 if (sm == null) {
  • 1220 return;
  • 1221 }
  • 1222 processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
  • 1223 WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
  • 1224 Boolean result = Caches.subclassAudits.get(key);
  • 1225 if (result == null) {
  • 1226 result = Boolean.valueOf(auditSubclass(cl));
  • 1227 Caches.subclassAudits.putIfAbsent(key, result);
  • 1228 }
  • 1229 if (result.booleanValue()) {
  • 1230 return;
  • 1231 }
  • 1232 sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  • 1233 }
  • 1234
  • 1235 /**
  • 1236 * Performs reflective checks on given subclass to verify that it doesn't
  • 1237 * override security-sensitive non-final methods. Returns true if subclass
  • 1238 * is "safe", false otherwise.
  • 1239 */
  • 1240 private static boolean auditSubclass(final Class subcl) {
  • 1241 Boolean result = (Boolean) AccessController.doPrivileged(
  • 1242 new PrivilegedAction() {
  • 1243 public Object run() {
  • 1244 for (Class cl = subcl;
  • 1245 cl != ObjectInputStream.class;
  • 1246 cl = cl.getSuperclass())
  • 1247 {
  • 1248 try {
  • 1249 cl.getDeclaredMethod(
  • 1250 "readUnshared", (Class[]) null);
  • 1251 return Boolean.FALSE;
  • 1252 } catch (NoSuchMethodException ex) {
  • 1253 }
  • 1254 try {
  • 1255 cl.getDeclaredMethod("readFields", (Class[]) null);
  • 1256 return Boolean.FALSE;
  • 1257 } catch (NoSuchMethodException ex) {
  • 1258 }
  • 1259 }
  • 1260 return Boolean.TRUE;
  • 1261 }
  • 1262 }
  • 1263 );
  • 1264 return result.booleanValue();
  • 1265 }
  • 1266
  • 1267 /**
  • 1268 * Clears internal data structures.
  • 1269 */
  • 1270 private void clear() {
  • 1271 handles.clear();
  • 1272 vlist.clear();
  • 1273 }
  • 1274
  • 1275 /**
  • 1276 * Underlying readObject implementation.
  • 1277 */
  • 1278 private Object readObject0(boolean unshared) throws IOException {
  • 1279 boolean oldMode = bin.getBlockDataMode();
  • 1280 if (oldMode) {
  • 1281 int remain = bin.currentBlockRemaining();
  • 1282 if (remain > 0) {
  • 1283 throw new OptionalDataException(remain);
  • 1284 } else if (defaultDataEnd) {
  • 1285 /*
  • 1286 * Fix for 4360508: stream is currently at the end of a field
  • 1287 * value block written via default serialization; since there
  • 1288 * is no terminating TC_ENDBLOCKDATA tag, simulate
  • 1289 * end-of-custom-data behavior explicitly.
  • 1290 */
  • 1291 throw new OptionalDataException(true);
  • 1292 }
  • 1293 bin.setBlockDataMode(false);
  • 1294 }
  • 1295
  • 1296 byte tc;
  • 1297 while ((tc = bin.peekByte()) == TC_RESET) {
  • 1298 bin.readByte();
  • 1299 handleReset();
  • 1300 }
  • 1301
  • 1302 depth++;
  • 1303 try {
  • 1304 switch (tc) {
  • 1305 case TC_NULL:
  • 1306 return readNull();
  • 1307
  • 1308 case TC_REFERENCE:
  • 1309 return readHandle(unshared);
  • 1310
  • 1311 case TC_CLASS:
  • 1312 return readClass(unshared);
  • 1313
  • 1314 case TC_CLASSDESC:
  • 1315 case TC_PROXYCLASSDESC:
  • 1316 return readClassDesc(unshared);
  • 1317
  • 1318 case TC_STRING:
  • 1319 case TC_LONGSTRING:
  • 1320 return checkResolve(readString(unshared));
  • 1321
  • 1322 case TC_ARRAY:
  • 1323 return checkResolve(readArray(unshared));
  • 1324
  • 1325 case TC_ENUM:
  • 1326 return checkResolve(readEnum(unshared));
  • 1327
  • 1328 case TC_OBJECT:
  • 1329 return checkResolve(readOrdinaryObject(unshared));
  • 1330
  • 1331 case TC_EXCEPTION:
  • 1332 IOException ex = readFatalException();
  • 1333 throw new WriteAbortedException("writing aborted", ex);
  • 1334
  • 1335 case TC_BLOCKDATA:
  • 1336 case TC_BLOCKDATALONG:
  • 1337 if (oldMode) {
  • 1338 bin.setBlockDataMode(true);
  • 1339 bin.peek(); // force header read
  • 1340 throw new OptionalDataException(
  • 1341 bin.currentBlockRemaining());
  • 1342 } else {
  • 1343 throw new StreamCorruptedException(
  • 1344 "unexpected block data");
  • 1345 }
  • 1346
  • 1347 case TC_ENDBLOCKDATA:
  • 1348 if (oldMode) {
  • 1349 throw new OptionalDataException(true);
  • 1350 } else {
  • 1351 throw new StreamCorruptedException(
  • 1352 "unexpected end of block data");
  • 1353 }
  • 1354
  • 1355 default:
  • 1356 throw new StreamCorruptedException(
  • 1357 String.format("invalid type code: %02X", tc));
  • 1358 }
  • 1359 } finally {
  • 1360 depth--;
  • 1361 bin.setBlockDataMode(oldMode);
  • 1362 }
  • 1363 }
  • 1364
  • 1365 /**
  • 1366 * If resolveObject has been enabled and given object does not have an
  • 1367 * exception associated with it, calls resolveObject to determine
  • 1368 * replacement for object, and updates handle table accordingly. Returns
  • 1369 * replacement object, or echoes provided object if no replacement
  • 1370 * occurred. Expects that passHandle is set to given object's handle prior
  • 1371 * to calling this method.
  • 1372 */
  • 1373 private Object checkResolve(Object obj) throws IOException {
  • 1374 if (!enableResolve || handles.lookupException(passHandle) != null) {
  • 1375 return obj;
  • 1376 }
  • 1377 Object rep = resolveObject(obj);
  • 1378 if (rep != obj) {
  • 1379 handles.setObject(passHandle, rep);
  • 1380 }
  • 1381 return rep;
  • 1382 }
  • 1383
  • 1384 /**
  • 1385 * Reads string without allowing it to be replaced in stream. Called from
  • 1386 * within ObjectStreamClass.read().
  • 1387 */
  • 1388 String readTypeString() throws IOException {
  • 1389 int oldHandle = passHandle;
  • 1390 try {
  • 1391 byte tc = bin.peekByte();
  • 1392 switch (tc) {
  • 1393 case TC_NULL:
  • 1394 return (String) readNull();
  • 1395
  • 1396 case TC_REFERENCE:
  • 1397 return (String) readHandle(false);
  • 1398
  • 1399 case TC_STRING:
  • 1400 case TC_LONGSTRING:
  • 1401 return readString(false);
  • 1402
  • 1403 default:
  • 1404 throw new StreamCorruptedException(
  • 1405 String.format("invalid type code: %02X", tc));
  • 1406 }
  • 1407 } finally {
  • 1408 passHandle = oldHandle;
  • 1409 }
  • 1410 }
  • 1411
  • 1412 /**
  • 1413 * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
  • 1414 */
  • 1415 private Object readNull() throws IOException {
  • 1416 if (bin.readByte() != TC_NULL) {
  • 1417 throw new InternalError();
  • 1418 }
  • 1419 passHandle = NULL_HANDLE;
  • 1420 return null;
  • 1421 }
  • 1422
  • 1423 /**
  • 1424 * Reads in object handle, sets passHandle to the read handle, and returns
  • 1425 * object associated with the handle.
  • 1426 */
  • 1427 private Object readHandle(boolean unshared) throws IOException {
  • 1428 if (bin.readByte() != TC_REFERENCE) {
  • 1429 throw new InternalError();
  • 1430 }
  • 1431 passHandle = bin.readInt() - baseWireHandle;
  • 1432 if (passHandle < 0 || passHandle >= handles.size()) {
  • 1433 throw new StreamCorruptedException(
  • 1434 String.format("invalid handle value: %08X", passHandle +
  • 1435 baseWireHandle));
  • 1436 }
  • 1437 if (unshared) {
  • 1438 // REMIND: what type of exception to throw here?
  • 1439 throw new InvalidObjectException(
  • 1440 "cannot read back reference as unshared");
  • 1441 }
  • 1442
  • 1443 Object obj = handles.lookupObject(passHandle);
  • 1444 if (obj == unsharedMarker) {
  • 1445 // REMIND: what type of exception to throw here?
  • 1446 throw new InvalidObjectException(
  • 1447 "cannot read back reference to unshared object");
  • 1448 }
  • 1449 return obj;
  • 1450 }
  • 1451
  • 1452 /**
  • 1453 * Reads in and returns class object. Sets passHandle to class object's
  • 1454 * assigned handle. Returns null if class is unresolvable (in which case a
  • 1455 * ClassNotFoundException will be associated with the class' handle in the
  • 1456 * handle table).
  • 1457 */
  • 1458 private Class readClass(boolean unshared) throws IOException {
  • 1459 if (bin.readByte() != TC_CLASS) {
  • 1460 throw new InternalError();
  • 1461 }
  • 1462 ObjectStreamClass desc = readClassDesc(false);
  • 1463 Class cl = desc.forClass();
  • 1464 passHandle = handles.assign(unshared ? unsharedMarker : cl);
  • 1465
  • 1466 ClassNotFoundException resolveEx = desc.getResolveException();
  • 1467 if (resolveEx != null) {
  • 1468 handles.markException(passHandle, resolveEx);
  • 1469 }
  • 1470
  • 1471 handles.finish(passHandle);
  • 1472 return cl;
  • 1473 }
  • 1474
  • 1475 /**
  • 1476 * Reads in and returns (possibly null) class descriptor. Sets passHandle
  • 1477 * to class descriptor's assigned handle. If class descriptor cannot be
  • 1478 * resolved to a class in the local VM, a ClassNotFoundException is
  • 1479 * associated with the class descriptor's handle.
  • 1480 */
  • 1481 private ObjectStreamClass readClassDesc(boolean unshared)
  • 1482 throws IOException
  • 1483 {
  • 1484 byte tc = bin.peekByte();
  • 1485 switch (tc) {
  • 1486 case TC_NULL:
  • 1487 return (ObjectStreamClass) readNull();
  • 1488
  • 1489 case TC_REFERENCE:
  • 1490 return (ObjectStreamClass) readHandle(unshared);
  • 1491
  • 1492 case TC_PROXYCLASSDESC:
  • 1493 return readProxyDesc(unshared);
  • 1494
  • 1495 case TC_CLASSDESC:
  • 1496 return readNonProxyDesc(unshared);
  • 1497
  • 1498 default:
  • 1499 throw new StreamCorruptedException(
  • 1500 String.format("invalid type code: %02X", tc));
  • 1501 }
  • 1502 }
  • 1503
  • 1504 /**
  • 1505 * Reads in and returns class descriptor for a dynamic proxy class. Sets
  • 1506 * passHandle to proxy class descriptor's assigned handle. If proxy class
  • 1507 * descriptor cannot be resolved to a class in the local VM, a
  • 1508 * ClassNotFoundException is associated with the descriptor's handle.
  • 1509 */
  • 1510 private ObjectStreamClass readProxyDesc(boolean unshared)
  • 1511 throws IOException
  • 1512 {
  • 1513 if (bin.readByte() != TC_PROXYCLASSDESC) {
  • 1514 throw new InternalError();
  • 1515 }
  • 1516
  • 1517 ObjectStreamClass desc = new ObjectStreamClass();
  • 1518 int descHandle = handles.assign(unshared ? unsharedMarker : desc);
  • 1519 passHandle = NULL_HANDLE;
  • 1520
  • 1521 int numIfaces = bin.readInt();
  • 1522 String[] ifaces = new String[numIfaces];
  • 1523 for (int i = 0; i < numIfaces; i++) {
  • 1524 ifaces[i] = bin.readUTF();
  • 1525 }
  • 1526
  • 1527 Class cl = null;
  • 1528 ClassNotFoundException resolveEx = null;
  • 1529 bin.setBlockDataMode(true);
  • 1530 try {
  • 1531 if ((cl = resolveProxyClass(ifaces)) == null) {
  • 1532 resolveEx = new ClassNotFoundException("null class");
  • 1533 }
  • 1534 } catch (ClassNotFoundException ex) {
  • 1535 resolveEx = ex;
  • 1536 }
  • 1537 skipCustomData();
  • 1538
  • 1539 desc.initProxy(cl, resolveEx, readClassDesc(false));
  • 1540
  • 1541 handles.finish(descHandle);
  • 1542 passHandle = descHandle;
  • 1543 return desc;
  • 1544 }
  • 1545
  • 1546 /**
  • 1547 * Reads in and returns class descriptor for a class that is not a dynamic
  • 1548 * proxy class. Sets passHandle to class descriptor's assigned handle. If
  • 1549 * class descriptor cannot be resolved to a class in the local VM, a
  • 1550 * ClassNotFoundException is associated with the descriptor's handle.
  • 1551 */
  • 1552 private ObjectStreamClass readNonProxyDesc(boolean unshared)
  • 1553 throws IOException
  • 1554 {
  • 1555 if (bin.readByte() != TC_CLASSDESC) {
  • 1556 throw new InternalError();
  • 1557 }
  • 1558
  • 1559 ObjectStreamClass desc = new ObjectStreamClass();
  • 1560 int descHandle = handles.assign(unshared ? unsharedMarker : desc);
  • 1561 passHandle = NULL_HANDLE;
  • 1562
  • 1563 ObjectStreamClass readDesc = null;
  • 1564 try {
  • 1565 readDesc = readClassDescriptor();
  • 1566 } catch (ClassNotFoundException ex) {
  • 1567 throw (IOException) new InvalidClassException(
  • 1568 "failed to read class descriptor").initCause(ex);
  • 1569 }
  • 1570
  • 1571 Class cl = null;
  • 1572 ClassNotFoundException resolveEx = null;
  • 1573 bin.setBlockDataMode(true);
  • 1574 try {
  • 1575 if ((cl = resolveClass(readDesc)) == null) {
  • 1576 resolveEx = new ClassNotFoundException("null class");
  • 1577 }
  • 1578 } catch (ClassNotFoundException ex) {
  • 1579 resolveEx = ex;
  • 1580 }
  • 1581 skipCustomData();
  • 1582
  • 1583 desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
  • 1584
  • 1585 handles.finish(descHandle);
  • 1586 passHandle = descHandle;
  • 1587 return desc;
  • 1588 }
  • 1589
  • 1590 /**
  • 1591 * Reads in and returns new string. Sets passHandle to new string's
  • 1592 * assigned handle.
  • 1593 */
  • 1594 private String readString(boolean unshared) throws IOException {
  • 1595 String str;
  • 1596 byte tc = bin.readByte();
  • 1597 switch (tc) {
  • 1598 case TC_STRING:
  • 1599 str = bin.readUTF();
  • 1600 break;
  • 1601
  • 1602 case TC_LONGSTRING:
  • 1603 str = bin.readLongUTF();
  • 1604 break;
  • 1605
  • 1606 default:
  • 1607 throw new StreamCorruptedException(
  • 1608 String.format("invalid type code: %02X", tc));
  • 1609 }
  • 1610 passHandle = handles.assign(unshared ? unsharedMarker : str);
  • 1611 handles.finish(passHandle);
  • 1612 return str;
  • 1613 }
  • 1614
  • 1615 /**
  • 1616 * Reads in and returns array object, or null if array class is
  • 1617 * unresolvable. Sets passHandle to array's assigned handle.
  • 1618 */
  • 1619 private Object readArray(boolean unshared) throws IOException {
  • 1620 if (bin.readByte() != TC_ARRAY) {
  • 1621 throw new InternalError();
  • 1622 }
  • 1623
  • 1624 ObjectStreamClass desc = readClassDesc(false);
  • 1625 int len = bin.readInt();
  • 1626
  • 1627 Object array = null;
  • 1628 Class cl, ccl = null;
  • 1629 if ((cl = desc.forClass()) != null) {
  • 1630 ccl = cl.getComponentType();
  • 1631 array = Array.newInstance(ccl, len);
  • 1632 }
  • 1633
  • 1634 int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
  • 1635 ClassNotFoundException resolveEx = desc.getResolveException();
  • 1636 if (resolveEx != null) {
  • 1637 handles.markException(arrayHandle, resolveEx);
  • 1638 }
  • 1639
  • 1640 if (ccl == null) {
  • 1641 for (int i = 0; i < len; i++) {
  • 1642 readObject0(false);
  • 1643 }
  • 1644 } else if (ccl.isPrimitive()) {
  • 1645 if (ccl == Integer.TYPE) {
  • 1646 bin.readInts((int[]) array, 0, len);
  • 1647 } else if (ccl == Byte.TYPE) {
  • 1648 bin.readFully((byte[]) array, 0, len, true);
  • 1649 } else if (ccl == Long.TYPE) {
  • 1650 bin.readLongs((long[]) array, 0, len);
  • 1651 } else if (ccl == Float.TYPE) {
  • 1652 bin.readFloats((float[]) array, 0, len);
  • 1653 } else if (ccl == Double.TYPE) {
  • 1654 bin.readDoubles((double[]) array, 0, len);
  • 1655 } else if (ccl == Short.TYPE) {
  • 1656 bin.readShorts((short[]) array, 0, len);
  • 1657 } else if (ccl == Character.TYPE) {
  • 1658 bin.readChars((char[]) array, 0, len);
  • 1659 } else if (ccl == Boolean.TYPE) {
  • 1660 bin.readBooleans((boolean[]) array, 0, len);
  • 1661 } else {
  • 1662 throw new InternalError();
  • 1663 }
  • 1664 } else {
  • 1665 Object[] oa = (Object[]) array;
  • 1666 for (int i = 0; i < len; i++) {
  • 1667 oa[i] = readObject0(false);
  • 1668 handles.markDependency(arrayHandle, passHandle);
  • 1669 }
  • 1670 }
  • 1671
  • 1672 handles.finish(arrayHandle);
  • 1673 passHandle = arrayHandle;
  • 1674 return array;
  • 1675 }
  • 1676
  • 1677 /**
  • 1678 * Reads in and returns enum constant, or null if enum type is
  • 1679 * unresolvable. Sets passHandle to enum constant's assigned handle.
  • 1680 */
  • 1681 private Enum readEnum(boolean unshared) throws IOException {
  • 1682 if (bin.readByte() != TC_ENUM) {
  • 1683 throw new InternalError();
  • 1684 }
  • 1685
  • 1686 ObjectStreamClass desc = readClassDesc(false);
  • 1687 if (!desc.isEnum()) {
  • 1688 throw new InvalidClassException("non-enum class: " + desc);
  • 1689 }
  • 1690
  • 1691 int enumHandle = handles.assign(unshared ? unsharedMarker : null);
  • 1692 ClassNotFoundException resolveEx = desc.getResolveException();
  • 1693 if (resolveEx != null) {
  • 1694 handles.markException(enumHandle, resolveEx);
  • 1695 }
  • 1696
  • 1697 String name = readString(false);
  • 1698 Enum en = null;
  • 1699 Class cl = desc.forClass();
  • 1700 if (cl != null) {
  • 1701 try {
  • 1702 en = Enum.valueOf(cl, name);
  • 1703 } catch (IllegalArgumentException ex) {
  • 1704 throw (IOException) new InvalidObjectException(
  • 1705 "enum constant " + name + " does not exist in " +
  • 1706 cl).initCause(ex);
  • 1707 }
  • 1708 if (!unshared) {
  • 1709 handles.setObject(enumHandle, en);
  • 1710 }
  • 1711 }
  • 1712
  • 1713 handles.finish(enumHandle);
  • 1714 passHandle = enumHandle;
  • 1715 return en;
  • 1716 }
  • 1717
  • 1718 /**
  • 1719 * Reads and returns "ordinary" (i.e., not a String, Class,
  • 1720 * ObjectStreamClass, array, or enum constant) object, or null if object's
  • 1721 * class is unresolvable (in which case a ClassNotFoundException will be
  • 1722 * associated with object's handle). Sets passHandle to object's assigned
  • 1723 * handle.
  • 1724 */
  • 1725 private Object readOrdinaryObject(boolean unshared)
  • 1726 throws IOException
  • 1727 {
  • 1728 if (bin.readByte() != TC_OBJECT) {
  • 1729 throw new InternalError();
  • 1730 }
  • 1731
  • 1732 ObjectStreamClass desc = readClassDesc(false);
  • 1733 desc.checkDeserialize();
  • 1734
  • 1735 Object obj;
  • 1736 try {
  • 1737 obj = desc.isInstantiable() ? desc.newInstance() : null;
  • 1738 } catch (Exception ex) {
  • 1739 throw (IOException) new InvalidClassException(
  • 1740 desc.forClass().getName(),
  • 1741 "unable to create instance").initCause(ex);
  • 1742 }
  • 1743
  • 1744 passHandle = handles.assign(unshared ? unsharedMarker : obj);
  • 1745 ClassNotFoundException resolveEx = desc.getResolveException();
  • 1746 if (resolveEx != null) {
  • 1747 handles.markException(passHandle, resolveEx);
  • 1748 }
  • 1749
  • 1750 if (desc.isExternalizable()) {
  • 1751 readExternalData((Externalizable) obj, desc);
  • 1752 } else {
  • 1753 readSerialData(obj, desc);
  • 1754 }
  • 1755
  • 1756 handles.finish(passHandle);
  • 1757
  • 1758 if (obj != null &&
  • 1759 handles.lookupException(passHandle) == null &&
  • 1760 desc.hasReadResolveMethod())
  • 1761 {
  • 1762 Object rep = desc.invokeReadResolve(obj);
  • 1763 if (unshared && rep.getClass().isArray()) {
  • 1764 rep = cloneArray(rep);
  • 1765 }
  • 1766 if (rep != obj) {
  • 1767 handles.setObject(passHandle, obj = rep);
  • 1768 }
  • 1769 }
  • 1770
  • 1771 return obj;
  • 1772 }
  • 1773
  • 1774 /**
  • 1775 * If obj is non-null, reads externalizable data by invoking readExternal()
  • 1776 * method of obj; otherwise, attempts to skip over externalizable data.
  • 1777 * Expects that passHandle is set to obj's handle before this method is
  • 1778 * called.
  • 1779 */
  • 1780 private void readExternalData(Externalizable obj, ObjectStreamClass desc)
  • 1781 throws IOException
  • 1782 {
  • 1783 CallbackContext oldContext = curContext;
  • 1784 curContext = null;
  • 1785
  • 1786 boolean blocked = desc.hasBlockExternalData();
  • 1787 if (blocked) {
  • 1788 bin.setBlockDataMode(true);
  • 1789 }
  • 1790 if (obj != null) {
  • 1791 try {
  • 1792 obj.readExternal(this);
  • 1793 } catch (ClassNotFoundException ex) {
  • 1794 /*
  • 1795 * In most cases, the handle table has already propagated a
  • 1796 * CNFException to passHandle at this point; this mark call is
  • 1797 * included to address cases where the readExternal method has
  • 1798 * cons'ed and thrown a new CNFException of its own.
  • 1799 */
  • 1800 handles.markException(passHandle, ex);
  • 1801 }
  • 1802 }
  • 1803 if (blocked) {
  • 1804 skipCustomData();
  • 1805 }
  • 1806
  • 1807 /*
  • 1808 * At this point, if the externalizable data was not written in
  • 1809 * block-data form and either the externalizable class doesn't exist
  • 1810 * locally (i.e., obj == null) or readExternal() just threw a
  • 1811 * CNFException, then the stream is probably in an inconsistent state,
  • 1812 * since some (or all) of the externalizable data may not have been
  • 1813 * consumed. Since there's no "correct" action to take in this case,
  • 1814 * we mimic the behavior of past serialization implementations and
  • 1815 * blindly hope that the stream is in sync; if it isn't and additional
  • 1816 * externalizable data remains in the stream, a subsequent read will
  • 1817 * most likely throw a StreamCorruptedException.
  • 1818 */
  • 1819
  • 1820 curContext = oldContext;
  • 1821 }
  • 1822
  • 1823 /**
  • 1824 * Reads (or attempts to skip, if obj is null or is tagged with a
  • 1825 * ClassNotFoundException) instance data for each serializable class of
  • 1826 * object in stream, from superclass to subclass. Expects that passHandle
  • 1827 * is set to obj's handle before this method is called.
  • 1828 */
  • 1829 private void readSerialData(Object obj, ObjectStreamClass desc)
  • 1830 throws IOException
  • 1831 {
  • 1832 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
  • 1833 for (int i = 0; i < slots.length; i++) {
  • 1834 ObjectStreamClass slotDesc = slots[i].desc;
  • 1835
  • 1836 if (slots[i].hasData) {
  • 1837 if (obj != null &&
  • 1838 slotDesc.hasReadObjectMethod() &&
  • 1839 handles.lookupException(passHandle) == null)
  • 1840 {
  • 1841 CallbackContext oldContext = curContext;
  • 1842 curContext = new CallbackContext(obj, slotDesc);
  • 1843
  • 1844 bin.setBlockDataMode(true);
  • 1845 try {
  • 1846 slotDesc.invokeReadObject(obj, this);
  • 1847 } catch (ClassNotFoundException ex) {
  • 1848 /*
  • 1849 * In most cases, the handle table has already
  • 1850 * propagated a CNFException to passHandle at this
  • 1851 * point; this mark call is included to address cases
  • 1852 * where the custom readObject method has cons'ed and
  • 1853 * thrown a new CNFException of its own.
  • 1854 */
  • 1855 handles.markException(passHandle, ex);
  • 1856 } finally {
  • 1857 curContext.setUsed();
  • 1858 }
  • 1859
  • 1860 curContext = oldContext;
  • 1861
  • 1862 /*
  • 1863 * defaultDataEnd may have been set indirectly by custom
  • 1864 * readObject() method when calling defaultReadObject() or
  • 1865 * readFields(); clear it to restore normal read behavior.
  • 1866 */
  • 1867 defaultDataEnd = false;
  • 1868 } else {
  • 1869 defaultReadFields(obj, slotDesc);
  • 1870 }
  • 1871 if (slotDesc.hasWriteObjectData()) {
  • 1872 skipCustomData();
  • 1873 } else {
  • 1874 bin.setBlockDataMode(false);
  • 1875 }
  • 1876 } else {
  • 1877 if (obj != null &&
  • 1878 slotDesc.hasReadObjectNoDataMethod() &&
  • 1879 handles.lookupException(passHandle) == null)
  • 1880 {
  • 1881 slotDesc.invokeReadObjectNoData(obj);
  • 1882 }
  • 1883 }
  • 1884 }
  • 1885 }
  • 1886
  • 1887 /**
  • 1888 * Skips over all block data and objects until TC_ENDBLOCKDATA is
  • 1889 * encountered.
  • 1890 */
  • 1891 private void skipCustomData() throws IOException {
  • 1892 int oldHandle = passHandle;
  • 1893 for (;;) {
  • 1894 if (bin.getBlockDataMode()) {
  • 1895 bin.skipBlockData();
  • 1896 bin.setBlockDataMode(false);
  • 1897 }
  • 1898 switch (bin.peekByte()) {
  • 1899 case TC_BLOCKDATA:
  • 1900 case TC_BLOCKDATALONG:
  • 1901 bin.setBlockDataMode(true);
  • 1902 break;
  • 1903
  • 1904 case TC_ENDBLOCKDATA:
  • 1905 bin.readByte();
  • 1906 passHandle = oldHandle;
  • 1907 return;
  • 1908
  • 1909 default:
  • 1910 readObject0(false);
  • 1911 break;
  • 1912 }
  • 1913 }
  • 1914 }
  • 1915
  • 1916 /**
  • 1917 * Reads in values of serializable fields declared by given class
  • 1918 * descriptor. If obj is non-null, sets field values in obj. Expects that
  • 1919 * passHandle is set to obj's handle before this method is called.
  • 1920 */
  • 1921 private void defaultReadFields(Object obj, ObjectStreamClass desc)
  • 1922 throws IOException
  • 1923 {
  • 1924 // REMIND: is isInstance check necessary?
  • 1925 Class cl = desc.forClass();
  • 1926 if (cl != null && obj != null && !cl.isInstance(obj)) {
  • 1927 throw new ClassCastException();
  • 1928 }
  • 1929
  • 1930 int primDataSize = desc.getPrimDataSize();
  • 1931 if (primVals == null || primVals.length < primDataSize) {
  • 1932 primVals = new byte[primDataSize];
  • 1933 }
  • 1934 bin.readFully(primVals, 0, primDataSize, false);
  • 1935 if (obj != null) {
  • 1936 desc.setPrimFieldValues(obj, primVals);
  • 1937 }
  • 1938
  • 1939 int objHandle = passHandle;
  • 1940 ObjectStreamField[] fields = desc.getFields(false);
  • 1941 Object[] objVals = new Object[desc.getNumObjFields()];
  • 1942 int numPrimFields = fields.length - objVals.length;
  • 1943 for (int i = 0; i < objVals.length; i++) {
  • 1944 ObjectStreamField f = fields[numPrimFields + i];
  • 1945 objVals[i] = readObject0(f.isUnshared());
  • 1946 if (f.getField() != null) {
  • 1947 handles.markDependency(objHandle, passHandle);
  • 1948 }
  • 1949 }
  • 1950 if (obj != null) {
  • 1951 desc.setObjFieldValues(obj, objVals);
  • 1952 }
  • 1953 passHandle = objHandle;
  • 1954 }
  • 1955
  • 1956 /**
  • 1957 * Reads in and returns IOException that caused serialization to abort.
  • 1958 * All stream state is discarded prior to reading in fatal exception. Sets
  • 1959 * passHandle to fatal exception's handle.
  • 1960 */
  • 1961 private IOException readFatalException() throws IOException {
  • 1962 if (bin.readByte() != TC_EXCEPTION) {
  • 1963 throw new InternalError();
  • 1964 }
  • 1965 clear();
  • 1966 return (IOException) readObject0(false);
  • 1967 }
  • 1968
  • 1969 /**
  • 1970 * If recursion depth is 0, clears internal data structures; otherwise,
  • 1971 * throws a StreamCorruptedException. This method is called when a
  • 1972 * TC_RESET typecode is encountered.
  • 1973 */
  • 1974 private void handleReset() throws StreamCorruptedException {
  • 1975 if (depth > 0) {
  • 1976 throw new StreamCorruptedException(
  • 1977 "unexpected reset; recursion depth: " + depth);
  • 1978 }
  • 1979 clear();
  • 1980 }
  • 1981
  • 1982 /**
  • 1983 * Converts specified span of bytes into float values.
  • 1984 */
  • 1985 // REMIND: remove once hotspot inlines Float.intBitsToFloat
  • 1986 private static native void bytesToFloats(byte[] src, int srcpos,
  • 1987 float[] dst, int dstpos,
  • 1988 int nfloats);
  • 1989
  • 1990 /**
  • 1991 * Converts specified span of bytes into double values.
  • 1992 */
  • 1993 // REMIND: remove once hotspot inlines Double.longBitsToDouble
  • 1994 private static native void bytesToDoubles(byte[] src, int srcpos,
  • 1995 double[] dst, int dstpos,
  • 1996 int ndoubles);
  • 1997
  • 1998 /**
  • 1999 * Returns the first non-null class loader (not counting class loaders of
  • 2000 * generated reflection implementation classes) up the execution stack, or
  • 2001 * null if only code from the null class loader is on the stack. This
  • 2002 * method is also called via reflection by the following RMI-IIOP class:
  • 2003 *
  • 2004 * com.sun.corba.se.internal.util.JDKClassLoader
  • 2005 *
  • 2006 * This method should not be removed or its signature changed without
  • 2007 * corresponding modifications to the above class.
  • 2008 */
  • 2009 // REMIND: change name to something more accurate?
  • 2010 private static native ClassLoader latestUserDefinedLoader();
  • 2011
  • 2012 /**
  • 2013 * Default GetField implementation.
  • 2014 */
  • 2015 private class GetFieldImpl extends GetField {
  • 2016
  • 2017 /** class descriptor describing serializable fields */
  • 2018 private final ObjectStreamClass desc;
  • 2019 /** primitive field values */
  • 2020 private final byte[] primVals;
  • 2021 /** object field values */
  • 2022 private final Object[] objVals;
  • 2023 /** object field value handles */
  • 2024 private final int[] objHandles;
  • 2025
  • 2026 /**
  • 2027 * Creates GetFieldImpl object for reading fields defined in given
  • 2028 * class descriptor.
  • 2029 */
  • 2030 GetFieldImpl(ObjectStreamClass desc) {
  • 2031 this.desc = desc;
  • 2032 primVals = new byte[desc.getPrimDataSize()];
  • 2033 objVals = new Object[desc.getNumObjFields()];
  • 2034 objHandles = new int[objVals.length];
  • 2035 }
  • 2036
  • 2037 public ObjectStreamClass getObjectStreamClass() {
  • 2038 return desc;
  • 2039 }
  • 2040
  • 2041 public boolean defaulted(String name) throws IOException {
  • 2042 return (getFieldOffset(name, null) < 0);
  • 2043 }
  • 2044
  • 2045 public boolean get(String name, boolean val) throws IOException {
  • 2046 int off = getFieldOffset(name, Boolean.TYPE);
  • 2047 return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
  • 2048 }
  • 2049
  • 2050 public byte get(String name, byte val) throws IOException {
  • 2051 int off = getFieldOffset(name, Byte.TYPE);
  • 2052 return (off >= 0) ? primVals[off] : val;
  • 2053 }
  • 2054
  • 2055 public char get(String name, char val) throws IOException {
  • 2056 int off = getFieldOffset(name, Character.TYPE);
  • 2057 return (off >= 0) ? Bits.getChar(primVals, off) : val;
  • 2058 }
  • 2059
  • 2060 public short get(String name, short val) throws IOException {
  • 2061 int off = getFieldOffset(name, Short.TYPE);
  • 2062 return (off >= 0) ? Bits.getShort(primVals, off) : val;
  • 2063 }
  • 2064
  • 2065 public int get(String name, int val) throws IOException {
  • 2066 int off = getFieldOffset(name, Integer.TYPE);
  • 2067 return (off >= 0) ? Bits.getInt(primVals, off) : val;
  • 2068 }
  • 2069
  • 2070 public float get(String name, float val) throws IOException {
  • 2071 int off = getFieldOffset(name, Float.TYPE);
  • 2072 return (off >= 0) ? Bits.getFloat(primVals, off) : val;
  • 2073 }
  • 2074
  • 2075 public long get(String name, long val) throws IOException {
  • 2076 int off = getFieldOffset(name, Long.TYPE);
  • 2077 return (off >= 0) ? Bits.getLong(primVals, off) : val;
  • 2078 }
  • 2079
  • 2080 public double get(String name, double val) throws IOException {
  • 2081 int off = getFieldOffset(name, Double.TYPE);
  • 2082 return (off >= 0) ? Bits.getDouble(primVals, off) : val;
  • 2083 }
  • 2084
  • 2085 public Object get(String name, Object val) throws IOException {
  • 2086 int off = getFieldOffset(name, Object.class);
  • 2087 if (off >= 0) {
  • 2088 int objHandle = objHandles[off];
  • 2089 handles.markDependency(passHandle, objHandle);
  • 2090 return (handles.lookupException(objHandle) == null) ?
  • 2091 objVals[off] : null;
  • 2092 } else {
  • 2093 return val;
  • 2094 }
  • 2095 }
  • 2096
  • 2097 /**
  • 2098 * Reads primitive and object field values from stream.
  • 2099 */
  • 2100 void readFields() throws IOException {
  • 2101 bin.readFully(primVals, 0, primVals.length, false);
  • 2102
  • 2103 int oldHandle = passHandle;
  • 2104 ObjectStreamField[] fields = desc.getFields(false);
  • 2105 int numPrimFields = fields.length - objVals.length;
  • 2106 for (int i = 0; i < objVals.length; i++) {
  • 2107 objVals[i] =
  • 2108 readObject0(fields[numPrimFields + i].isUnshared());
  • 2109 objHandles[i] = passHandle;
  • 2110 }
  • 2111 passHandle = oldHandle;
  • 2112 }
  • 2113
  • 2114 /**
  • 2115 * Returns offset of field with given name and type. A specified type
  • 2116 * of null matches all types, Object.class matches all non-primitive
  • 2117 * types, and any other non-null type matches assignable types only.
  • 2118 * If no matching field is found in the (incoming) class
  • 2119 * descriptor but a matching field is present in the associated local
  • 2120 * class descriptor, returns -1. Throws IllegalArgumentException if
  • 2121 * neither incoming nor local class descriptor contains a match.
  • 2122 */
  • 2123 private int getFieldOffset(String name, Class type) {
  • 2124 ObjectStreamField field = desc.getField(name, type);
  • 2125 if (field != null) {
  • 2126 return field.getOffset();
  • 2127 } else if (desc.getLocalDesc().getField(name, type) != null) {
  • 2128 return -1;
  • 2129 } else {
  • 2130 throw new IllegalArgumentException("no such field " + name +
  • 2131 " with type " + type);
  • 2132 }
  • 2133 }
  • 2134 }
  • 2135
  • 2136 /**
  • 2137 * Prioritized list of callbacks to be performed once object graph has been
  • 2138 * completely deserialized.
  • 2139 */
  • 2140 private static class ValidationList {
  • 2141
  • 2142 private static class Callback {
  • 2143 final ObjectInputValidation obj;
  • 2144 final int priority;
  • 2145 Callback next;
  • 2146 final AccessControlContext acc;
  • 2147
  • 2148 Callback(ObjectInputValidation obj, int priority, Callback next,
  • 2149 AccessControlContext acc)
  • 2150 {
  • 2151 this.obj = obj;
  • 2152 this.priority = priority;
  • 2153 this.next = next;
  • 2154 this.acc = acc;
  • 2155 }
  • 2156 }
  • 2157
  • 2158 /** linked list of callbacks */
  • 2159 private Callback list;
  • 2160
  • 2161 /**
  • 2162 * Creates new (empty) ValidationList.
  • 2163 */
  • 2164 ValidationList() {
  • 2165 }
  • 2166
  • 2167 /**
  • 2168 * Registers callback. Throws InvalidObjectException if callback
  • 2169 * object is null.
  • 2170 */
  • 2171 void register(ObjectInputValidation obj, int priority)
  • 2172 throws InvalidObjectException
  • 2173 {
  • 2174 if (obj == null) {
  • 2175 throw new InvalidObjectException("null callback");
  • 2176 }
  • 2177
  • 2178 Callback prev = null, cur = list;
  • 2179 while (cur != null && priority < cur.priority) {
  • 2180 prev = cur;
  • 2181 cur = cur.next;
  • 2182 }
  • 2183 AccessControlContext acc = AccessController.getContext();
  • 2184 if (prev != null) {
  • 2185 prev.next = new Callback(obj, priority, cur, acc);
  • 2186 } else {
  • 2187 list = new Callback(obj, priority, list, acc);
  • 2188 }
  • 2189 }
  • 2190
  • 2191 /**
  • 2192 * Invokes all registered callbacks and clears the callback list.
  • 2193 * Callbacks with higher priorities are called first; those with equal
  • 2194 * priorities may be called in any order. If any of the callbacks
  • 2195 * throws an InvalidObjectException, the callback process is terminated
  • 2196 * and the exception propagated upwards.
  • 2197 */
  • 2198 void doCallbacks() throws InvalidObjectException {
  • 2199 try {
  • 2200 while (list != null) {
  • 2201 AccessController.doPrivileged(
  • 2202 new PrivilegedExceptionAction()
  • 2203 {
  • 2204 public Object run() throws InvalidObjectException {
  • 2205 list.obj.validateObject();
  • 2206 return null;
  • 2207 }
  • 2208 }, list.acc);
  • 2209 list = list.next;
  • 2210 }
  • 2211 } catch (PrivilegedActionException ex) {
  • 2212 list = null;
  • 2213 throw (InvalidObjectException) ex.getException();
  • 2214 }
  • 2215 }
  • 2216
  • 2217 /**
  • 2218 * Resets the callback list to its initial (empty) state.
  • 2219 */
  • 2220 public void clear() {
  • 2221 list = null;
  • 2222 }
  • 2223 }
  • 2224
  • 2225 /**
  • 2226 * Input stream supporting single-byte peek operations.
  • 2227 */
  • 2228 private static class PeekInputStream extends InputStream {
  • 2229
  • 2230 /** underlying stream */
  • 2231 private final InputStream in;
  • 2232 /** peeked byte */
  • 2233 private int peekb = -1;
  • 2234
  • 2235 /**
  • 2236 * Creates new PeekInputStream on top of given underlying stream.
  • 2237 */
  • 2238 PeekInputStream(InputStream in) {
  • 2239 this.in = in;
  • 2240 }
  • 2241
  • 2242 /**
  • 2243 * Peeks at next byte value in stream. Similar to read(), except
  • 2244 * that it does not consume the read value.
  • 2245 */
  • 2246 int peek() throws IOException {
  • 2247 return (peekb >= 0) ? peekb : (peekb = in.read());
  • 2248 }
  • 2249
  • 2250 public int read() throws IOException {
  • 2251 if (peekb >= 0) {
  • 2252 int v = peekb;
  • 2253 peekb = -1;
  • 2254 return v;
  • 2255 } else {
  • 2256 return in.read();
  • 2257 }
  • 2258 }
  • 2259
  • 2260 public int read(byte[] b, int off, int len) throws IOException {
  • 2261 if (len == 0) {
  • 2262 return 0;
  • 2263 } else if (peekb < 0) {
  • 2264 return in.read(b, off, len);
  • 2265 } else {
  • 2266 b[off++] = (byte) peekb;
  • 2267 len--;
  • 2268 peekb = -1;
  • 2269 int n = in.read(b, off, len);
  • 2270 return (n >= 0) ? (n + 1) : 1;
  • 2271 }
  • 2272 }
  • 2273
  • 2274 void readFully(byte[] b, int off, int len) throws IOException {
  • 2275 int n = 0;
  • 2276 while (n < len) {
  • 2277 int count = read(b, off + n, len - n);
  • 2278 if (count < 0) {
  • 2279 throw new EOFException();
  • 2280 }
  • 2281 n += count;
  • 2282 }
  • 2283 }
  • 2284
  • 2285 public long skip(long n) throws IOException {
  • 2286 if (n <= 0) {
  • 2287 return 0;
  • 2288 }
  • 2289 int skipped = 0;
  • 2290 if (peekb >= 0) {
  • 2291 peekb = -1;
  • 2292 skipped++;
  • 2293 n--;
  • 2294 }
  • 2295 return skipped + skip(n);
  • 2296 }
  • 2297
  • 2298 public int available() throws IOException {
  • 2299 return in.available() + ((peekb >= 0) ? 1 : 0);
  • 2300 }
  • 2301
  • 2302 public void close() throws IOException {
  • 2303 in.close();
  • 2304 }
  • 2305 }
  • 2306
  • 2307 /**
  • 2308 * Input stream with two modes: in default mode, inputs data written in the
  • 2309 * same format as DataOutputStream; in "block data" mode, inputs data
  • 2310 * bracketed by block data markers (see object serialization specification
  • 2311 * for details). Buffering depends on block data mode: when in default
  • 2312 * mode, no data is buffered in advance; when in block data mode, all data
  • 2313 * for the current data block is read in at once (and buffered).
  • 2314 */
  • 2315 private class BlockDataInputStream
  • 2316 extends InputStream implements DataInput
  • 2317 {
  • 2318 /** maximum data block length */
  • 2319 private static final int MAX_BLOCK_SIZE = 1024;
  • 2320 /** maximum data block header length */
  • 2321 private static final int MAX_HEADER_SIZE = 5;
  • 2322 /** (tunable) length of char buffer (for reading strings) */
  • 2323 private static final int CHAR_BUF_SIZE = 256;
  • 2324 /** readBlockHeader() return value indicating header read may block */
  • 2325 private static final int HEADER_BLOCKED = -2;
  • 2326
  • 2327 /** buffer for reading general/block data */
  • 2328 private final byte[] buf = new byte[MAX_BLOCK_SIZE];
  • 2329 /** buffer for reading block data headers */
  • 2330 private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
  • 2331 /** char buffer for fast string reads */
  • 2332 private final char[] cbuf = new char[CHAR_BUF_SIZE];
  • 2333
  • 2334 /** block data mode */
  • 2335 private boolean blkmode = false;
  • 2336
  • 2337 // block data state fields; values meaningful only when blkmode true
  • 2338 /** current offset into buf */
  • 2339 private int pos = 0;
  • 2340 /** end offset of valid data in buf, or -1 if no more block data */
  • 2341 private int end = -1;
  • 2342 /** number of bytes in current block yet to be read from stream */
  • 2343 private int unread = 0;
  • 2344
  • 2345 /** underlying stream (wrapped in peekable filter stream) */
  • 2346 private final PeekInputStream in;
  • 2347 /** loopback stream (for data reads that span data blocks) */
  • 2348 private final DataInputStream din;
  • 2349
  • 2350 /**
  • 2351 * Creates new BlockDataInputStream on top of given underlying stream.
  • 2352 * Block data mode is turned off by default.
  • 2353 */
  • 2354 BlockDataInputStream(InputStream in) {
  • 2355 this.in = new PeekInputStream(in);
  • 2356 din = new DataInputStream(this);
  • 2357 }
  • 2358
  • 2359 /**
  • 2360 * Sets block data mode to the given mode (true == on, false == off)
  • 2361 * and returns the previous mode value. If the new mode is the same as
  • 2362 * the old mode, no action is taken. Throws IllegalStateException if
  • 2363 * block data mode is being switched from on to off while unconsumed
  • 2364 * block data is still present in the stream.
  • 2365 */
  • 2366 boolean setBlockDataMode(boolean newmode) throws IOException {
  • 2367 if (blkmode == newmode) {
  • 2368 return blkmode;
  • 2369 }
  • 2370 if (newmode) {
  • 2371 pos = 0;
  • 2372 end = 0;
  • 2373 unread = 0;
  • 2374 } else if (pos < end) {
  • 2375 throw new IllegalStateException("unread block data");
  • 2376 }
  • 2377 blkmode = newmode;
  • 2378 return !blkmode;
  • 2379 }
  • 2380
  • 2381 /**
  • 2382 * Returns true if the stream is currently in block data mode, false
  • 2383 * otherwise.
  • 2384 */
  • 2385 boolean getBlockDataMode() {
  • 2386 return blkmode;
  • 2387 }
  • 2388
  • 2389 /**
  • 2390 * If in block data mode, skips to the end of the current group of data
  • 2391 * blocks (but does not unset block data mode). If not in block data
  • 2392 * mode, throws an IllegalStateException.
  • 2393 */
  • 2394 void skipBlockData() throws IOException {
  • 2395 if (!blkmode) {
  • 2396 throw new IllegalStateException("not in block data mode");
  • 2397 }
  • 2398 while (end >= 0) {
  • 2399 refill();
  • 2400 }
  • 2401 }
  • 2402
  • 2403 /**
  • 2404 * Attempts to read in the next block data header (if any). If
  • 2405 * canBlock is false and a full header cannot be read without possibly
  • 2406 * blocking, returns HEADER_BLOCKED, else if the next element in the
  • 2407 * stream is a block data header, returns the block data length
  • 2408 * specified by the header, else returns -1.
  • 2409 */
  • 2410 private int readBlockHeader(boolean canBlock) throws IOException {
  • 2411 if (defaultDataEnd) {
  • 2412 /*
  • 2413 * Fix for 4360508: stream is currently at the end of a field
  • 2414 * value block written via default serialization; since there
  • 2415 * is no terminating TC_ENDBLOCKDATA tag, simulate
  • 2416 * end-of-custom-data behavior explicitly.
  • 2417 */
  • 2418 return -1;
  • 2419 }
  • 2420 try {
  • 2421 for (;;) {
  • 2422 int avail = canBlock ? Integer.MAX_VALUE : in.available();
  • 2423 if (avail == 0) {
  • 2424 return HEADER_BLOCKED;
  • 2425 }
  • 2426
  • 2427 int tc = in.peek();
  • 2428 switch (tc) {
  • 2429 case TC_BLOCKDATA:
  • 2430 if (avail < 2) {
  • 2431 return HEADER_BLOCKED;
  • 2432 }
  • 2433 in.readFully(hbuf, 0, 2);
  • 2434 return hbuf[1] & 0xFF;
  • 2435
  • 2436 case TC_BLOCKDATALONG:
  • 2437 if (avail < 5) {
  • 2438 return HEADER_BLOCKED;
  • 2439 }
  • 2440 in.readFully(hbuf, 0, 5);
  • 2441 int len = Bits.getInt(hbuf, 1);
  • 2442 if (len < 0) {
  • 2443 throw new StreamCorruptedException(
  • 2444 "illegal block data header length: " +
  • 2445 len);
  • 2446 }
  • 2447 return len;
  • 2448
  • 2449 /*
  • 2450 * TC_RESETs may occur in between data blocks.
  • 2451 * Unfortunately, this case must be parsed at a lower
  • 2452 * level than other typecodes, since primitive data
  • 2453 * reads may span data blocks separated by a TC_RESET.
  • 2454 */
  • 2455 case TC_RESET:
  • 2456 in.read();
  • 2457 handleReset();
  • 2458 break;
  • 2459
  • 2460 default:
  • 2461 if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
  • 2462 throw new StreamCorruptedException(
  • 2463 String.format("invalid type code: %02X",
  • 2464 tc));
  • 2465 }
  • 2466 return -1;
  • 2467 }
  • 2468 }
  • 2469 } catch (EOFException ex) {
  • 2470 throw new StreamCorruptedException(
  • 2471 "unexpected EOF while reading block data header");
  • 2472 }
  • 2473 }
  • 2474
  • 2475 /**
  • 2476 * Refills internal buffer buf with block data. Any data in buf at the
  • 2477 * time of the call is considered consumed. Sets the pos, end, and
  • 2478 * unread fields to reflect the new amount of available block data; if
  • 2479 * the next element in the stream is not a data block, sets pos and
  • 2480 * unread to 0 and end to -1.
  • 2481 */
  • 2482 private void refill() throws IOException {
  • 2483 try {
  • 2484 do {
  • 2485 pos = 0;
  • 2486 if (unread > 0) {
  • 2487 int n =
  • 2488 in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
  • 2489 if (n >= 0) {
  • 2490 end = n;
  • 2491 unread -= n;
  • 2492 } else {
  • 2493 throw new StreamCorruptedException(
  • 2494 "unexpected EOF in middle of data block");
  • 2495 }
  • 2496 } else {
  • 2497 int n = readBlockHeader(true);
  • 2498 if (n >= 0) {
  • 2499 end = 0;
  • 2500 unread = n;
  • 2501 } else {
  • 2502 end = -1;
  • 2503 unread = 0;
  • 2504 }
  • 2505 }
  • 2506 } while (pos == end);
  • 2507 } catch (IOException ex) {
  • 2508 pos = 0;
  • 2509 end = -1;
  • 2510 unread = 0;
  • 2511 throw ex;
  • 2512 }
  • 2513 }
  • 2514
  • 2515 /**
  • 2516 * If in block data mode, returns the number of unconsumed bytes
  • 2517 * remaining in the current data block. If not in block data mode,
  • 2518 * throws an IllegalStateException.
  • 2519 */
  • 2520 int currentBlockRemaining() {
  • 2521 if (blkmode) {
  • 2522 return (end >= 0) ? (end - pos) + unread : 0;
  • 2523 } else {
  • 2524 throw new IllegalStateException();
  • 2525 }
  • 2526 }
  • 2527
  • 2528 /**
  • 2529 * Peeks at (but does not consume) and returns the next byte value in
  • 2530 * the stream, or -1 if the end of the stream/block data (if in block
  • 2531 * data mode) has been reached.
  • 2532 */
  • 2533 int peek() throws IOException {
  • 2534 if (blkmode) {
  • 2535 if (pos == end) {
  • 2536 refill();
  • 2537 }
  • 2538 return (end >= 0) ? (buf[pos] & 0xFF) : -1;
  • 2539 } else {
  • 2540 return in.peek();
  • 2541 }
  • 2542 }
  • 2543
  • 2544 /**
  • 2545 * Peeks at (but does not consume) and returns the next byte value in
  • 2546 * the stream, or throws EOFException if end of stream/block data has
  • 2547 * been reached.
  • 2548 */
  • 2549 byte peekByte() throws IOException {
  • 2550 int val = peek();
  • 2551 if (val < 0) {
  • 2552 throw new EOFException();
  • 2553 }
  • 2554 return (byte) val;
  • 2555 }
  • 2556
  • 2557
  • 2558 /* ----------------- generic input stream methods ------------------ */
  • 2559 /*
  • 2560 * The following methods are equivalent to their counterparts in
  • 2561 * InputStream, except that they interpret data block boundaries and
  • 2562 * read the requested data from within data blocks when in block data
  • 2563 * mode.
  • 2564 */
  • 2565
  • 2566 public int read() throws IOException {
  • 2567 if (blkmode) {
  • 2568 if (pos == end) {
  • 2569 refill();
  • 2570 }
  • 2571 return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
  • 2572 } else {
  • 2573 return in.read();
  • 2574 }
  • 2575 }
  • 2576
  • 2577 public int read(byte[] b, int off, int len) throws IOException {
  • 2578 return read(b, off, len, false);
  • 2579 }
  • 2580
  • 2581 public long skip(long len) throws IOException {
  • 2582 long remain = len;
  • 2583 while (remain > 0) {
  • 2584 if (blkmode) {
  • 2585 if (pos == end) {
  • 2586 refill();
  • 2587 }
  • 2588 if (end < 0) {
  • 2589 break;
  • 2590 }
  • 2591 int nread = (int) Math.min(remain, end - pos);
  • 2592 remain -= nread;
  • 2593 pos += nread;
  • 2594 } else {
  • 2595 int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
  • 2596 if ((nread = in.read(buf, 0, nread)) < 0) {
  • 2597 break;
  • 2598 }
  • 2599 remain -= nread;
  • 2600 }
  • 2601 }
  • 2602 return len - remain;
  • 2603 }
  • 2604
  • 2605 public int available() throws IOException {
  • 2606 if (blkmode) {
  • 2607 if ((pos == end) && (unread == 0)) {
  • 2608 int n;
  • 2609 while ((n = readBlockHeader(false)) == 0) ;
  • 2610 switch (n) {
  • 2611 case HEADER_BLOCKED:
  • 2612 break;
  • 2613
  • 2614 case -1:
  • 2615 pos = 0;
  • 2616 end = -1;
  • 2617 break;
  • 2618
  • 2619 default:
  • 2620 pos = 0;
  • 2621 end = 0;
  • 2622 unread = n;
  • 2623 break;
  • 2624 }
  • 2625 }
  • 2626 // avoid unnecessary call to in.available() if possible
  • 2627 int unreadAvail = (unread > 0) ?
  • 2628 Math.min(in.available(), unread) : 0;
  • 2629 return (end >= 0) ? (end - pos) + unreadAvail : 0;
  • 2630 } else {
  • 2631 return in.available();
  • 2632 }
  • 2633 }
  • 2634
  • 2635 public void close() throws IOException {
  • 2636 if (blkmode) {
  • 2637 pos = 0;
  • 2638 end = -1;
  • 2639 unread = 0;
  • 2640 }
  • 2641 in.close();
  • 2642 }
  • 2643
  • 2644 /**
  • 2645 * Attempts to read len bytes into byte array b at offset off. Returns
  • 2646 * the number of bytes read, or -1 if the end of stream/block data has
  • 2647 * been reached. If copy is true, reads values into an intermediate
  • 2648 * buffer before copying them to b (to avoid exposing a reference to
  • 2649 * b).
  • 2650 */
  • 2651 int read(byte[] b, int off, int len, boolean copy) throws IOException {
  • 2652 if (len == 0) {
  • 2653 return 0;
  • 2654 } else if (blkmode) {
  • 2655 if (pos == end) {
  • 2656 refill();
  • 2657 }
  • 2658 if (end < 0) {
  • 2659 return -1;
  • 2660 }
  • 2661 int nread = Math.min(len, end - pos);
  • 2662 System.arraycopy(buf, pos, b, off, nread);
  • 2663 pos += nread;
  • 2664 return nread;
  • 2665 } else if (copy) {
  • 2666 int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
  • 2667 if (nread > 0) {
  • 2668 System.arraycopy(buf, 0, b, off, nread);
  • 2669 }
  • 2670 return nread;
  • 2671 } else {
  • 2672 return in.read(b, off, len);
  • 2673 }
  • 2674 }
  • 2675
  • 2676 /* ----------------- primitive data input methods ------------------ */
  • 2677 /*
  • 2678 * The following methods are equivalent to their counterparts in
  • 2679 * DataInputStream, except that they interpret data block boundaries
  • 2680 * and read the requested data from within data blocks when in block
  • 2681 * data mode.
  • 2682 */
  • 2683
  • 2684 public void readFully(byte[] b) throws IOException {
  • 2685 readFully(b, 0, b.length, false);
  • 2686 }
  • 2687
  • 2688 public void readFully(byte[] b, int off, int len) throws IOException {
  • 2689 readFully(b, off, len, false);
  • 2690 }
  • 2691
  • 2692 public void readFully(byte[] b, int off, int len, boolean copy)
  • 2693 throws IOException
  • 2694 {
  • 2695 while (len > 0) {
  • 2696 int n = read(b, off, len, copy);
  • 2697 if (n < 0) {
  • 2698 throw new EOFException();
  • 2699 }
  • 2700 off += n;
  • 2701 len -= n;
  • 2702 }
  • 2703 }
  • 2704
  • 2705 public int skipBytes(int n) throws IOException {
  • 2706 return din.skipBytes(n);
  • 2707 }
  • 2708
  • 2709 public boolean readBoolean() throws IOException {
  • 2710 int v = read();
  • 2711 if (v < 0) {
  • 2712 throw new EOFException();
  • 2713 }
  • 2714 return (v != 0);
  • 2715 }
  • 2716
  • 2717 public byte readByte() throws IOException {
  • 2718 int v = read();
  • 2719 if (v < 0) {
  • 2720 throw new EOFException();
  • 2721 }
  • 2722 return (byte) v;
  • 2723 }
  • 2724
  • 2725 public int readUnsignedByte() throws IOException {
  • 2726 int v = read();
  • 2727 if (v < 0) {
  • 2728 throw new EOFException();
  • 2729 }
  • 2730 return v;
  • 2731 }
  • 2732
  • 2733 public char readChar() throws IOException {
  • 2734 if (!blkmode) {
  • 2735 pos = 0;
  • 2736 in.readFully(buf, 0, 2);
  • 2737 } else if (end - pos < 2) {
  • 2738 return din.readChar();
  • 2739 }
  • 2740 char v = Bits.getChar(buf, pos);
  • 2741 pos += 2;
  • 2742 return v;
  • 2743 }
  • 2744
  • 2745 public short readShort() throws IOException {
  • 2746 if (!blkmode) {
  • 2747 pos = 0;
  • 2748 in.readFully(buf, 0, 2);
  • 2749 } else if (end - pos < 2) {
  • 2750 return din.readShort();
  • 2751 }
  • 2752 short v = Bits.getShort(buf, pos);
  • 2753 pos += 2;
  • 2754 return v;
  • 2755 }
  • 2756
  • 2757 public int readUnsignedShort() throws IOException {
  • 2758 if (!blkmode) {
  • 2759 pos = 0;
  • 2760 in.readFully(buf, 0, 2);
  • 2761 } else if (end - pos < 2) {
  • 2762 return din.readUnsignedShort();
  • 2763 }
  • 2764 int v = Bits.getShort(buf, pos) & 0xFFFF;
  • 2765 pos += 2;
  • 2766 return v;
  • 2767 }
  • 2768
  • 2769 public int readInt() throws IOException {
  • 2770 if (!blkmode) {
  • 2771 pos = 0;
  • 2772 in.readFully(buf, 0, 4);
  • 2773 } else if (end - pos < 4) {
  • 2774 return din.readInt();
  • 2775 }
  • 2776 int v = Bits.getInt(buf, pos);
  • 2777 pos += 4;
  • 2778 return v;
  • 2779 }
  • 2780
  • 2781 public float readFloat() throws IOException {
  • 2782 if (!blkmode) {
  • 2783 pos = 0;
  • 2784 in.readFully(buf, 0, 4);
  • 2785 } else if (end - pos < 4) {
  • 2786 return din.readFloat();
  • 2787 }
  • 2788 float v = Bits.getFloat(buf, pos);
  • 2789 pos += 4;
  • 2790 return v;
  • 2791 }
  • 2792
  • 2793 public long readLong() throws IOException {
  • 2794 if (!blkmode) {
  • 2795 pos = 0;
  • 2796 in.readFully(buf, 0, 8);
  • 2797 } else if (end - pos < 8) {
  • 2798 return din.readLong();
  • 2799 }
  • 2800 long v = Bits.getLong(buf, pos);
  • 2801 pos += 8;
  • 2802 return v;
  • 2803 }
  • 2804
  • 2805 public double readDouble() throws IOException {
  • 2806 if (!blkmode) {
  • 2807 pos = 0;
  • 2808 in.readFully(buf, 0, 8);
  • 2809 } else if (end - pos < 8) {
  • 2810 return din.readDouble();
  • 2811 }
  • 2812 double v = Bits.getDouble(buf, pos);
  • 2813 pos += 8;
  • 2814 return v;
  • 2815 }
  • 2816
  • 2817 public String readUTF() throws IOException {
  • 2818 return readUTFBody(readUnsignedShort());
  • 2819 }
  • 2820
  • 2821 public String readLine() throws IOException {
  • 2822 return din.readLine(); // deprecated, not worth optimizing
  • 2823 }
  • 2824
  • 2825 /* -------------- primitive data array input methods --------------- */
  • 2826 /*
  • 2827 * The following methods read in spans of primitive data values.
  • 2828 * Though equivalent to calling the corresponding primitive read
  • 2829 * methods repeatedly, these methods are optimized for reading groups
  • 2830 * of primitive data values more efficiently.
  • 2831 */
  • 2832
  • 2833 void readBooleans(boolean[] v, int off, int len) throws IOException {
  • 2834 int stop, endoff = off + len;
  • 2835 while (off < endoff) {
  • 2836 if (!blkmode) {
  • 2837 int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
  • 2838 in.readFully(buf, 0, span);
  • 2839 stop = off + span;
  • 2840 pos = 0;
  • 2841 } else if (end - pos < 1) {
  • 2842 v[off++] = din.readBoolean();
  • 2843 continue;
  • 2844 } else {
  • 2845 stop = Math.min(endoff, off + end - pos);
  • 2846 }
  • 2847
  • 2848 while (off < stop) {
  • 2849 v[off++] = Bits.getBoolean(buf, pos++);
  • 2850 }
  • 2851 }
  • 2852 }
  • 2853
  • 2854 void readChars(char[] v, int off, int len) throws IOException {
  • 2855 int stop, endoff = off + len;
  • 2856 while (off < endoff) {
  • 2857 if (!blkmode) {
  • 2858 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
  • 2859 in.readFully(buf, 0, span << 1);
  • 2860 stop = off + span;
  • 2861 pos = 0;
  • 2862 } else if (end - pos < 2) {
  • 2863 v[off++] = din.readChar();
  • 2864 continue;
  • 2865 } else {
  • 2866 stop = Math.min(endoff, off + ((end - pos) >> 1));
  • 2867 }
  • 2868
  • 2869 while (off < stop) {
  • 2870 v[off++] = Bits.getChar(buf, pos);
  • 2871 pos += 2;
  • 2872 }
  • 2873 }
  • 2874 }
  • 2875
  • 2876 void readShorts(short[] v, int off, int len) throws IOException {
  • 2877 int stop, endoff = off + len;
  • 2878 while (off < endoff) {
  • 2879 if (!blkmode) {
  • 2880 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
  • 2881 in.readFully(buf, 0, span << 1);
  • 2882 stop = off + span;
  • 2883 pos = 0;
  • 2884 } else if (end - pos < 2) {
  • 2885 v[off++] = din.readShort();
  • 2886 continue;
  • 2887 } else {
  • 2888 stop = Math.min(endoff, off + ((end - pos) >> 1));
  • 2889 }
  • 2890
  • 2891 while (off < stop) {
  • 2892 v[off++] = Bits.getShort(buf, pos);
  • 2893 pos += 2;
  • 2894 }
  • 2895 }
  • 2896 }
  • 2897
  • 2898 void readInts(int[] v, int off, int len) throws IOException {
  • 2899 int stop, endoff = off + len;
  • 2900 while (off < endoff) {
  • 2901 if (!blkmode) {
  • 2902 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
  • 2903 in.readFully(buf, 0, span << 2);
  • 2904 stop = off + span;
  • 2905 pos = 0;
  • 2906 } else if (end - pos < 4) {
  • 2907 v[off++] = din.readInt();
  • 2908 continue;
  • 2909 } else {
  • 2910 stop = Math.min(endoff, off + ((end - pos) >> 2));
  • 2911 }
  • 2912
  • 2913 while (off < stop) {
  • 2914 v[off++] = Bits.getInt(buf, pos);
  • 2915 pos += 4;
  • 2916 }
  • 2917 }
  • 2918 }
  • 2919
  • 2920 void readFloats(float[] v, int off, int len) throws IOException {
  • 2921 int span, endoff = off + len;
  • 2922 while (off < endoff) {
  • 2923 if (!blkmode) {
  • 2924 span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
  • 2925 in.readFully(buf, 0, span << 2);
  • 2926 pos = 0;
  • 2927 } else if (end - pos < 4) {
  • 2928 v[off++] = din.readFloat();
  • 2929 continue;
  • 2930 } else {
  • 2931 span = Math.min(endoff - off, ((end - pos) >> 2));
  • 2932 }
  • 2933
  • 2934 bytesToFloats(buf, pos, v, off, span);
  • 2935 off += span;
  • 2936 pos += span << 2;
  • 2937 }
  • 2938 }
  • 2939
  • 2940 void readLongs(long[] v, int off, int len) throws IOException {
  • 2941 int stop, endoff = off + len;
  • 2942 while (off < endoff) {
  • 2943 if (!blkmode) {
  • 2944 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
  • 2945 in.readFully(buf, 0, span << 3);
  • 2946 stop = off + span;
  • 2947 pos = 0;
  • 2948 } else if (end - pos < 8) {
  • 2949 v[off++] = din.readLong();
  • 2950 continue;
  • 2951 } else {
  • 2952 stop = Math.min(endoff, off + ((end - pos) >> 3));
  • 2953 }
  • 2954
  • 2955 while (off < stop) {
  • 2956 v[off++] = Bits.getLong(buf, pos);
  • 2957 pos += 8;
  • 2958 }
  • 2959 }
  • 2960 }
  • 2961
  • 2962 void readDoubles(double[] v, int off, int len) throws IOException {
  • 2963 int span, endoff = off + len;
  • 2964 while (off < endoff) {
  • 2965 if (!blkmode) {
  • 2966 span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
  • 2967 in.readFully(buf, 0, span << 3);
  • 2968 pos = 0;
  • 2969 } else if (end - pos < 8) {
  • 2970 v[off++] = din.readDouble();
  • 2971 continue;
  • 2972 } else {
  • 2973 span = Math.min(endoff - off, ((end - pos) >> 3));
  • 2974 }
  • 2975
  • 2976 bytesToDoubles(buf, pos, v, off, span);
  • 2977 off += span;
  • 2978 pos += span << 3;
  • 2979 }
  • 2980 }
  • 2981
  • 2982 /**
  • 2983 * Reads in string written in "long" UTF format. "Long" UTF format is
  • 2984 * identical to standard UTF, except that it uses an 8 byte header
  • 2985 * (instead of the standard 2 bytes) to convey the UTF encoding length.
  • 2986 */
  • 2987 String readLongUTF() throws IOException {
  • 2988 return readUTFBody(readLong());
  • 2989 }
  • 2990
  • 2991 /**
  • 2992 * Reads in the "body" (i.e., the UTF representation minus the 2-byte
  • 2993 * or 8-byte length header) of a UTF encoding, which occupies the next
  • 2994 * utflen bytes.
  • 2995 */
  • 2996 private String readUTFBody(long utflen) throws IOException {
  • 2997 StringBuilder sbuf = new StringBuilder();
  • 2998 if (!blkmode) {
  • 2999 end = pos = 0;
  • 3000 }
  • 3001
  • 3002 while (utflen > 0) {
  • 3003 int avail = end - pos;
  • 3004 if (avail >= 3 || (long) avail == utflen) {
  • 3005 utflen -= readUTFSpan(sbuf, utflen);
  • 3006 } else {
  • 3007 if (blkmode) {
  • 3008 // near block boundary, read one byte at a time
  • 3009 utflen -= readUTFChar(sbuf, utflen);
  • 3010 } else {
  • 3011 // shift and refill buffer manually
  • 3012 if (avail > 0) {
  • 3013 System.arraycopy(buf, pos, buf, 0, avail);
  • 3014 }
  • 3015 pos = 0;
  • 3016 end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
  • 3017 in.readFully(buf, avail, end - avail);
  • 3018 }
  • 3019 }
  • 3020 }
  • 3021
  • 3022 return sbuf.toString();
  • 3023 }
  • 3024
  • 3025 /**
  • 3026 * Reads span of UTF-encoded characters out of internal buffer
  • 3027 * (starting at offset pos and ending at or before offset end),
  • 3028 * consuming no more than utflen bytes. Appends read characters to
  • 3029 * sbuf. Returns the number of bytes consumed.
  • 3030 */
  • 3031 private long readUTFSpan(StringBuilder sbuf, long utflen)
  • 3032 throws IOException
  • 3033 {
  • 3034 int cpos = 0;
  • 3035 int start = pos;
  • 3036 int avail = Math.min(end - pos, CHAR_BUF_SIZE);
  • 3037 // stop short of last char unless all of utf bytes in buffer
  • 3038 int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
  • 3039 boolean outOfBounds = false;
  • 3040
  • 3041 try {
  • 3042 while (pos < stop) {
  • 3043 int b1, b2, b3;
  • 3044 b1 = buf[pos++] & 0xFF;
  • 3045 switch (b1 >> 4) {
  • 3046 case 0:
  • 3047 case 1:
  • 3048 case 2:
  • 3049 case 3:
  • 3050 case 4:
  • 3051 case 5:
  • 3052 case 6:
  • 3053 case 7: // 1 byte format: 0xxxxxxx
  • 3054 cbuf[cpos++] = (char) b1;
  • 3055 break;
  • 3056
  • 3057 case 12:
  • 3058 case 13: // 2 byte format: 110xxxxx 10xxxxxx
  • 3059 b2 = buf[pos++];
  • 3060 if ((b2 & 0xC0) != 0x80) {
  • 3061 throw new UTFDataFormatException();
  • 3062 }
  • 3063 cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
  • 3064 ((b2 & 0x3F) << 0));
  • 3065 break;
  • 3066
  • 3067 case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
  • 3068 b3 = buf[pos + 1];
  • 3069 b2 = buf[pos + 0];
  • 3070 pos += 2;
  • 3071 if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
  • 3072 throw new UTFDataFormatException();
  • 3073 }
  • 3074 cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
  • 3075 ((b2 & 0x3F) << 6) |
  • 3076 ((b3 & 0x3F) << 0));
  • 3077 break;
  • 3078
  • 3079 default: // 10xx xxxx, 1111 xxxx
  • 3080 throw new UTFDataFormatException();
  • 3081 }
  • 3082 }
  • 3083 } catch (ArrayIndexOutOfBoundsException ex) {
  • 3084 outOfBounds = true;
  • 3085 } finally {
  • 3086 if (outOfBounds || (pos - start) > utflen) {
  • 3087 /*
  • 3088 * Fix for 4450867: if a malformed utf char causes the
  • 3089 * conversion loop to scan past the expected end of the utf
  • 3090 * string, only consume the expected number of utf bytes.
  • 3091 */
  • 3092 pos = start + (int) utflen;
  • 3093 throw new UTFDataFormatException();
  • 3094 }
  • 3095 }
  • 3096
  • 3097 sbuf.append(cbuf, 0, cpos);
  • 3098 return pos - start;
  • 3099 }
  • 3100
  • 3101 /**
  • 3102 * Reads in single UTF-encoded character one byte at a time, appends
  • 3103 * the character to sbuf, and returns the number of bytes consumed.
  • 3104 * This method is used when reading in UTF strings written in block
  • 3105 * data mode to handle UTF-encoded characters which (potentially)
  • 3106 * straddle block-data boundaries.
  • 3107 */
  • 3108 private int readUTFChar(StringBuilder sbuf, long utflen)
  • 3109 throws IOException
  • 3110 {
  • 3111 int b1, b2, b3;
  • 3112 b1 = readByte() & 0xFF;
  • 3113 switch (b1 >> 4) {
  • 3114 case 0:
  • 3115 case 1:
  • 3116 case 2:
  • 3117 case 3:
  • 3118 case 4:
  • 3119 case 5:
  • 3120 case 6:
  • 3121 case 7: // 1 byte format: 0xxxxxxx
  • 3122 sbuf.append((char) b1);
  • 3123 return 1;
  • 3124
  • 3125 case 12:
  • 3126 case 13: // 2 byte format: 110xxxxx 10xxxxxx
  • 3127 if (utflen < 2) {
  • 3128 throw new UTFDataFormatException();
  • 3129 }
  • 3130 b2 = readByte();
  • 3131 if ((b2 & 0xC0) != 0x80) {
  • 3132 throw new UTFDataFormatException();
  • 3133 }
  • 3134 sbuf.append((char) (((b1 & 0x1F) << 6) |
  • 3135 ((b2 & 0x3F) << 0)));
  • 3136 return 2;
  • 3137
  • 3138 case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
  • 3139 if (utflen < 3) {
  • 3140 if (utflen == 2) {
  • 3141 readByte(); // consume remaining byte
  • 3142 }
  • 3143 throw new UTFDataFormatException();
  • 3144 }
  • 3145 b2 = readByte();
  • 3146 b3 = readByte();
  • 3147 if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
  • 3148 throw new UTFDataFormatException();
  • 3149 }
  • 3150 sbuf.append((char) (((b1 & 0x0F) << 12) |
  • 3151 ((b2 & 0x3F) << 6) |
  • 3152 ((b3 & 0x3F) << 0)));
  • 3153 return 3;
  • 3154
  • 3155 default: // 10xx xxxx, 1111 xxxx
  • 3156 throw new UTFDataFormatException();
  • 3157 }
  • 3158 }
  • 3159 }
  • 3160
  • 3161 /**
  • 3162 * Unsynchronized table which tracks wire handle to object mappings, as
  • 3163 * well as ClassNotFoundExceptions associated with deserialized objects.
  • 3164 * This class implements an exception-propagation algorithm for
  • 3165 * determining which objects should have ClassNotFoundExceptions associated
  • 3166 * with them, taking into account cycles and discontinuities (e.g., skipped
  • 3167 * fields) in the object graph.
  • 3168 *
  • 3169 * <p>General use of the table is as follows: during deserialization, a
  • 3170 * given object is first assigned a handle by calling the assign method.
  • 3171 * This method leaves the assigned handle in an "open" state, wherein
  • 3172 * dependencies on the exception status of other handles can be registered
  • 3173 * by calling the markDependency method, or an exception can be directly
  • 3174 * associated with the handle by calling markException. When a handle is
  • 3175 * tagged with an exception, the HandleTable assumes responsibility for
  • 3176 * propagating the exception to any other objects which depend
  • 3177 * (transitively) on the exception-tagged object.
  • 3178 *
  • 3179 * <p>Once all exception information/dependencies for the handle have been
  • 3180 * registered, the handle should be "closed" by calling the finish method
  • 3181 * on it. The act of finishing a handle allows the exception propagation
  • 3182 * algorithm to aggressively prune dependency links, lessening the
  • 3183 * performance/memory impact of exception tracking.
  • 3184 *
  • 3185 * <p>Note that the exception propagation algorithm used depends on handles
  • 3186 * being assigned/finished in LIFO order; however, for simplicity as well
  • 3187 * as memory conservation, it does not enforce this constraint.
  • 3188 */
  • 3189 // REMIND: add full description of exception propagation algorithm?
  • 3190 private static class HandleTable {
  • 3191
  • 3192 /* status codes indicating whether object has associated exception */
  • 3193 private static final byte STATUS_OK = 1;
  • 3194 private static final byte STATUS_UNKNOWN = 2;
  • 3195 private static final byte STATUS_EXCEPTION = 3;
  • 3196
  • 3197 /** array mapping handle -> object status */
  • 3198 byte[] status;
  • 3199 /** array mapping handle -> object/exception (depending on status) */
  • 3200 Object[] entries;
  • 3201 /** array mapping handle -> list of dependent handles (if any) */
  • 3202 HandleList[] deps;
  • 3203 /** lowest unresolved dependency */
  • 3204 int lowDep = -1;
  • 3205 /** number of handles in table */
  • 3206 int size = 0;
  • 3207
  • 3208 /**
  • 3209 * Creates handle table with the given initial capacity.
  • 3210 */
  • 3211 HandleTable(int initialCapacity) {
  • 3212 status = new byte[initialCapacity];
  • 3213 entries = new Object[initialCapacity];
  • 3214 deps = new HandleList[initialCapacity];
  • 3215 }
  • 3216
  • 3217 /**
  • 3218 * Assigns next available handle to given object, and returns assigned
  • 3219 * handle. Once object has been completely deserialized (and all
  • 3220 * dependencies on other objects identified), the handle should be
  • 3221 * "closed" by passing it to finish().
  • 3222 */
  • 3223 int assign(Object obj) {
  • 3224 if (size >= entries.length) {
  • 3225 grow();
  • 3226 }
  • 3227 status[size] = STATUS_UNKNOWN;
  • 3228 entries[size] = obj;
  • 3229 return size++;
  • 3230 }
  • 3231
  • 3232 /**
  • 3233 * Registers a dependency (in exception status) of one handle on
  • 3234 * another. The dependent handle must be "open" (i.e., assigned, but
  • 3235 * not finished yet). No action is taken if either dependent or target
  • 3236 * handle is NULL_HANDLE.
  • 3237 */
  • 3238 void markDependency(int dependent, int target) {
  • 3239 if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
  • 3240 return;
  • 3241 }
  • 3242 switch (status[dependent]) {
  • 3243
  • 3244 case STATUS_UNKNOWN:
  • 3245 switch (status[target]) {
  • 3246 case STATUS_OK:
  • 3247 // ignore dependencies on objs with no exception
  • 3248 break;
  • 3249
  • 3250 case STATUS_EXCEPTION:
  • 3251 // eagerly propagate exception
  • 3252 markException(dependent,
  • 3253 (ClassNotFoundException) entries[target]);
  • 3254 break;
  • 3255
  • 3256 case STATUS_UNKNOWN:
  • 3257 // add to dependency list of target
  • 3258 if (deps[target] == null) {
  • 3259 deps[target] = new HandleList();
  • 3260 }
  • 3261 deps[target].add(dependent);
  • 3262
  • 3263 // remember lowest unresolved target seen
  • 3264 if (lowDep < 0 || lowDep > target) {
  • 3265 lowDep = target;
  • 3266 }
  • 3267 break;
  • 3268
  • 3269 default:
  • 3270 throw new InternalError();
  • 3271 }
  • 3272 break;
  • 3273
  • 3274 case STATUS_EXCEPTION:
  • 3275 break;
  • 3276
  • 3277 default:
  • 3278 throw new InternalError();
  • 3279 }
  • 3280 }
  • 3281
  • 3282 /**
  • 3283 * Associates a ClassNotFoundException (if one not already associated)
  • 3284 * with the currently active handle and propagates it to other
  • 3285 * referencing objects as appropriate. The specified handle must be
  • 3286 * "open" (i.e., assigned, but not finished yet).
  • 3287 */
  • 3288 void markException(int handle, ClassNotFoundException ex) {
  • 3289 switch (status[handle]) {
  • 3290 case STATUS_UNKNOWN:
  • 3291 status[handle] = STATUS_EXCEPTION;
  • 3292 entries[handle] = ex;
  • 3293
  • 3294 // propagate exception to dependents
  • 3295 HandleList dlist = deps[handle];
  • 3296 if (dlist != null) {
  • 3297 int ndeps = dlist.size();
  • 3298 for (int i = 0; i < ndeps; i++) {
  • 3299 markException(dlist.get(i), ex);
  • 3300 }
  • 3301 deps[handle] = null;
  • 3302 }
  • 3303 break;
  • 3304
  • 3305 case STATUS_EXCEPTION:
  • 3306 break;
  • 3307
  • 3308 default:
  • 3309 throw new InternalError();
  • 3310 }
  • 3311 }
  • 3312
  • 3313 /**
  • 3314 * Marks given handle as finished, meaning that no new dependencies
  • 3315 * will be marked for handle. Calls to the assign and finish methods
  • 3316 * must occur in LIFO order.
  • 3317 */
  • 3318 void finish(int handle) {
  • 3319 int end;
  • 3320 if (lowDep < 0) {
  • 3321 // no pending unknowns, only resolve current handle
  • 3322 end = handle + 1;
  • 3323 } else if (lowDep >= handle) {
  • 3324 // pending unknowns now clearable, resolve all upward handles
  • 3325 end = size;
  • 3326 lowDep = -1;
  • 3327 } else {
  • 3328 // unresolved backrefs present, can't resolve anything yet
  • 3329 return;
  • 3330 }
  • 3331
  • 3332 // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
  • 3333 for (int i = handle; i < end; i++) {
  • 3334 switch (status[i]) {
  • 3335 case STATUS_UNKNOWN:
  • 3336 status[i] = STATUS_OK;
  • 3337 deps[i] = null;
  • 3338 break;
  • 3339
  • 3340 case STATUS_OK:
  • 3341 case STATUS_EXCEPTION:
  • 3342 break;
  • 3343
  • 3344 default:
  • 3345 throw new InternalError();
  • 3346 }
  • 3347 }
  • 3348 }
  • 3349
  • 3350 /**
  • 3351 * Assigns a new object to the given handle. The object previously
  • 3352 * associated with the handle is forgotten. This method has no effect
  • 3353 * if the given handle already has an exception associated with it.
  • 3354 * This method may be called at any time after the handle is assigned.
  • 3355 */
  • 3356 void setObject(int handle, Object obj) {
  • 3357 switch (status[handle]) {
  • 3358 case STATUS_UNKNOWN:
  • 3359 case STATUS_OK:
  • 3360 entries[handle] = obj;
  • 3361 break;
  • 3362
  • 3363 case STATUS_EXCEPTION:
  • 3364 break;
  • 3365
  • 3366 default:
  • 3367 throw new InternalError();
  • 3368 }
  • 3369 }
  • 3370
  • 3371 /**
  • 3372 * Looks up and returns object associated with the given handle.
  • 3373 * Returns null if the given handle is NULL_HANDLE, or if it has an
  • 3374 * associated ClassNotFoundException.
  • 3375 */
  • 3376 Object lookupObject(int handle) {
  • 3377 return (handle != NULL_HANDLE &&
  • 3378 status[handle] != STATUS_EXCEPTION) ?
  • 3379 entries[handle] : null;
  • 3380 }
  • 3381
  • 3382 /**
  • 3383 * Looks up and returns ClassNotFoundException associated with the
  • 3384 * given handle. Returns null if the given handle is NULL_HANDLE, or
  • 3385 * if there is no ClassNotFoundException associated with the handle.
  • 3386 */
  • 3387 ClassNotFoundException lookupException(int handle) {
  • 3388 return (handle != NULL_HANDLE &&
  • 3389 status[handle] == STATUS_EXCEPTION) ?
  • 3390 (ClassNotFoundException) entries[handle] : null;
  • 3391 }
  • 3392
  • 3393 /**
  • 3394 * Resets table to its initial state.
  • 3395 */
  • 3396 void clear() {
  • 3397 Arrays.fill(status, 0, size, (byte) 0);
  • 3398 Arrays.fill(entries, 0, size, null);
  • 3399 Arrays.fill(deps, 0, size, null);
  • 3400 lowDep = -1;
  • 3401 size = 0;
  • 3402 }
  • 3403
  • 3404 /**
  • 3405 * Returns number of handles registered in table.
  • 3406 */
  • 3407 int size() {
  • 3408 return size;
  • 3409 }
  • 3410
  • 3411 /**
  • 3412 * Expands capacity of internal arrays.
  • 3413 */
  • 3414 private void grow() {
  • 3415 int newCapacity = (entries.length << 1) + 1;
  • 3416
  • 3417 byte[] newStatus = new byte[newCapacity];
  • 3418 Object[] newEntries = new Object[newCapacity];
  • 3419 HandleList[] newDeps = new HandleList[newCapacity];
  • 3420
  • 3421 System.arraycopy(status, 0, newStatus, 0, size);
  • 3422 System.arraycopy(entries, 0, newEntries, 0, size);
  • 3423 System.arraycopy(deps, 0, newDeps, 0, size);
  • 3424
  • 3425 status = newStatus;
  • 3426 entries = newEntries;
  • 3427 deps = newDeps;
  • 3428 }
  • 3429
  • 3430 /**
  • 3431 * Simple growable list of (integer) handles.
  • 3432 */
  • 3433 private static class HandleList {
  • 3434 private int[] list = new int[4];
  • 3435 private int size = 0;
  • 3436
  • 3437 public HandleList() {
  • 3438 }
  • 3439
  • 3440 public void add(int handle) {
  • 3441 if (size >= list.length) {
  • 3442 int[] newList = new int[list.length << 1];
  • 3443 System.arraycopy(list, 0, newList, 0, list.length);
  • 3444 list = newList;
  • 3445 }
  • 3446 list[size++] = handle;
  • 3447 }
  • 3448
  • 3449 public int get(int index) {
  • 3450 if (index >= size) {
  • 3451 throw new ArrayIndexOutOfBoundsException();
  • 3452 }
  • 3453 return list[index];
  • 3454 }
  • 3455
  • 3456 public int size() {
  • 3457 return size;
  • 3458 }
  • 3459 }
  • 3460 }
  • 3461
  • 3462 /**
  • 3463 * Method for cloning arrays in case of using unsharing reading
  • 3464 */
  • 3465 private static Object cloneArray(Object array) {
  • 3466 if (array instanceof Object[]) {
  • 3467 return ((Object[]) array).clone();
  • 3468 } else if (array instanceof boolean[]) {
  • 3469 return ((boolean[]) array).clone();
  • 3470 } else if (array instanceof byte[]) {
  • 3471 return ((byte[]) array).clone();
  • 3472 } else if (array instanceof char[]) {
  • 3473 return ((char[]) array).clone();
  • 3474 } else if (array instanceof double[]) {
  • 3475 return ((double[]) array).clone();
  • 3476 } else if (array instanceof float[]) {
  • 3477 return ((float[]) array).clone();
  • 3478 } else if (array instanceof int[]) {
  • 3479 return ((int[]) array).clone();
  • 3480 } else if (array instanceof long[]) {
  • 3481 return ((long[]) array).clone();
  • 3482 } else if (array instanceof double[]) {
  • 3483 return ((double[]) array).clone();
  • 3484 } else {
  • 3485 throw new AssertionError();
  • 3486 }
  • 3487 }
  • 3488
  • 3489 /**
  • 3490 * Context that during upcalls to class-defined readObject methods; holds
  • 3491 * object currently being deserialized and descriptor for current class.
  • 3492 * This context keeps a boolean state to indicate that defaultReadObject
  • 3493 * or readFields has already been invoked with this context or the class's
  • 3494 * readObject method has returned; if true, the getObj method throws
  • 3495 * NotActiveException.
  • 3496 */
  • 3497 private static class CallbackContext {
  • 3498 private final Object obj;
  • 3499 private final ObjectStreamClass desc;
  • 3500 private final AtomicBoolean used = new AtomicBoolean();
  • 3501
  • 3502 public CallbackContext(Object obj, ObjectStreamClass desc) {
  • 3503 this.obj = obj;
  • 3504 this.desc = desc;
  • 3505 }
  • 3506
  • 3507 public Object getObj() throws NotActiveException {
  • 3508 checkAndSetUsed();
  • 3509 return obj;
  • 3510 }
  • 3511
  • 3512 public ObjectStreamClass getDesc() {
  • 3513 return desc;
  • 3514 }
  • 3515
  • 3516 private void checkAndSetUsed() throws NotActiveException {
  • 3517 if (!used.compareAndSet(false, true)) {
  • 3518 throw new NotActiveException(
  • 3519 "not in readObject invocation or fields already read");
  • 3520 }
  • 3521 }
  • 3522
  • 3523 public void setUsed() {
  • 3524 used.set(true);
  • 3525 }
  • 3526 }
  • 3527}

文件:ObjectInputStream.java
包名:java.io
类名:ObjectInputStream
继承:InputStream
接口:[ObjectInput][ObjectStreamConstants]