2 * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
28 import java.lang.reflect.Array;
29 import java.lang.reflect.Modifier;
30 import java.lang.reflect.Proxy;
31 import java.util.Arrays;
32 import java.util.HashMap;
33 import org.apidesign.bck2brwsr.emul.lang.System;
36 * An ObjectInputStream deserializes primitive data and objects previously
37 * written using an ObjectOutputStream.
39 * <p>ObjectOutputStream and ObjectInputStream can provide an application with
40 * persistent storage for graphs of objects when used with a FileOutputStream
41 * and FileInputStream respectively. ObjectInputStream is used to recover
42 * those objects previously serialized. Other uses include passing objects
43 * between hosts using a socket stream or for marshaling and unmarshaling
44 * arguments and parameters in a remote communication system.
46 * <p>ObjectInputStream ensures that the types of all objects in the graph
47 * created from the stream match the classes present in the Java Virtual
48 * Machine. Classes are loaded as required using the standard mechanisms.
50 * <p>Only objects that support the java.io.Serializable or
51 * java.io.Externalizable interface can be read from streams.
53 * <p>The method <code>readObject</code> is used to read an object from the
54 * stream. Java's safe casting should be used to get the desired type. In
55 * Java, strings and arrays are objects and are treated as objects during
56 * serialization. When read they need to be cast to the expected type.
58 * <p>Primitive data types can be read from the stream using the appropriate
59 * method on DataInput.
61 * <p>The default deserialization mechanism for objects restores the contents
62 * of each field to the value and type it had when it was written. Fields
63 * declared as transient or static are ignored by the deserialization process.
64 * References to other objects cause those objects to be read from the stream
65 * as necessary. Graphs of objects are restored correctly using a reference
66 * sharing mechanism. New objects are always allocated when deserializing,
67 * which prevents existing objects from being overwritten.
69 * <p>Reading an object is analogous to running the constructors of a new
70 * object. Memory is allocated for the object and initialized to zero (NULL).
71 * No-arg constructors are invoked for the non-serializable classes and then
72 * the fields of the serializable classes are restored from the stream starting
73 * with the serializable class closest to java.lang.object and finishing with
74 * the object's most specific class.
76 * <p>For example to read from a stream as written by the example in
80 * FileInputStream fis = new FileInputStream("t.tmp");
81 * ObjectInputStream ois = new ObjectInputStream(fis);
83 * int i = ois.readInt();
84 * String today = (String) ois.readObject();
85 * Date date = (Date) ois.readObject();
90 * <p>Classes control how they are serialized by implementing either the
91 * java.io.Serializable or java.io.Externalizable interfaces.
93 * <p>Implementing the Serializable interface allows object serialization to
94 * save and restore the entire state of the object and it allows classes to
95 * evolve between the time the stream is written and the time it is read. It
96 * automatically traverses references between objects, saving and restoring
99 * <p>Serializable classes that require special handling during the
100 * serialization and deserialization process should implement the following
104 * private void writeObject(java.io.ObjectOutputStream stream)
105 * throws IOException;
106 * private void readObject(java.io.ObjectInputStream stream)
107 * throws IOException, ClassNotFoundException;
108 * private void readObjectNoData()
109 * throws ObjectStreamException;
112 * <p>The readObject method is responsible for reading and restoring the state
113 * of the object for its particular class using data written to the stream by
114 * the corresponding writeObject method. The method does not need to concern
115 * itself with the state belonging to its superclasses or subclasses. State is
116 * restored by reading data from the ObjectInputStream for the individual
117 * fields and making assignments to the appropriate fields of the object.
118 * Reading primitive data types is supported by DataInput.
120 * <p>Any attempt to read object data which exceeds the boundaries of the
121 * custom data written by the corresponding writeObject method will cause an
122 * OptionalDataException to be thrown with an eof field value of true.
123 * Non-object reads which exceed the end of the allotted data will reflect the
124 * end of data in the same way that they would indicate the end of the stream:
125 * bytewise reads will return -1 as the byte read or number of bytes read, and
126 * primitive reads will throw EOFExceptions. If there is no corresponding
127 * writeObject method, then the end of default serialized data marks the end of
130 * <p>Primitive and object read calls issued from within a readExternal method
131 * behave in the same manner--if the stream is already positioned at the end of
132 * data written by the corresponding writeExternal method, object reads will
133 * throw OptionalDataExceptions with eof set to true, bytewise reads will
134 * return -1, and primitive reads will throw EOFExceptions. Note that this
135 * behavior does not hold for streams written with the old
136 * <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
137 * end of data written by writeExternal methods is not demarcated, and hence
138 * cannot be detected.
140 * <p>The readObjectNoData method is responsible for initializing the state of
141 * the object for its particular class in the event that the serialization
142 * stream does not list the given class as a superclass of the object being
143 * deserialized. This may occur in cases where the receiving party uses a
144 * different version of the deserialized instance's class than the sending
145 * party, and the receiver's version extends classes that are not extended by
146 * the sender's version. This may also occur if the serialization stream has
147 * been tampered; hence, readObjectNoData is useful for initializing
148 * deserialized objects properly despite a "hostile" or incomplete source
151 * <p>Serialization does not read or assign values to the fields of any object
152 * that does not implement the java.io.Serializable interface. Subclasses of
153 * Objects that are not serializable can be serializable. In this case the
154 * non-serializable class must have a no-arg constructor to allow its fields to
155 * be initialized. In this case it is the responsibility of the subclass to
156 * save and restore the state of the non-serializable class. It is frequently
157 * the case that the fields of that class are accessible (public, package, or
158 * protected) or that there are get and set methods that can be used to restore
161 * <p>Any exception that occurs while deserializing an object will be caught by
162 * the ObjectInputStream and abort the reading process.
164 * <p>Implementing the Externalizable interface allows the object to assume
165 * complete control over the contents and format of the object's serialized
166 * form. The methods of the Externalizable interface, writeExternal and
167 * readExternal, are called to save and restore the objects state. When
168 * implemented by a class they can write and read their own state using all of
169 * the methods of ObjectOutput and ObjectInput. It is the responsibility of
170 * the objects to handle any versioning that occurs.
172 * <p>Enum constants are deserialized differently than ordinary serializable or
173 * externalizable objects. The serialized form of an enum constant consists
174 * solely of its name; field values of the constant are not transmitted. To
175 * deserialize an enum constant, ObjectInputStream reads the constant name from
176 * the stream; the deserialized constant is then obtained by calling the static
177 * method <code>Enum.valueOf(Class, String)</code> with the enum constant's
178 * base type and the received constant name as arguments. Like other
179 * serializable or externalizable objects, enum constants can function as the
180 * targets of back references appearing subsequently in the serialization
181 * stream. The process by which enum constants are deserialized cannot be
182 * customized: any class-specific readObject, readObjectNoData, and readResolve
183 * methods defined by enum types are ignored during deserialization.
184 * Similarly, any serialPersistentFields or serialVersionUID field declarations
185 * are also ignored--all enum types have a fixed serialVersionUID of 0L.
187 * @author Mike Warres
188 * @author Roger Riggs
189 * @see java.io.DataInput
190 * @see java.io.ObjectOutputStream
191 * @see java.io.Serializable
192 * @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
195 public class ObjectInputStream
196 extends InputStream implements ObjectInput, ObjectStreamConstants
198 /** handle value representing null */
199 private static final int NULL_HANDLE = -1;
201 /** marker for unshared objects in internal handle table */
202 private static final Object unsharedMarker = new Object();
204 /** table mapping primitive type names to corresponding class objects */
205 private static final HashMap<String, Class<?>> primClasses
206 = new HashMap<>(8, 1.0F);
208 primClasses.put("boolean", boolean.class);
209 primClasses.put("byte", byte.class);
210 primClasses.put("char", char.class);
211 primClasses.put("short", short.class);
212 primClasses.put("int", int.class);
213 primClasses.put("long", long.class);
214 primClasses.put("float", float.class);
215 primClasses.put("double", double.class);
216 primClasses.put("void", void.class);
219 /** filter stream for handling block data conversion */
220 private final BlockDataInputStream bin;
221 /** validation callback list */
222 private final ValidationList vlist;
223 /** recursion depth */
225 /** whether stream is closed */
226 private boolean closed;
228 /** wire handle -> obj/exception map */
229 private final HandleTable handles;
230 /** scratch field for passing handle values up/down call stack */
231 private int passHandle = NULL_HANDLE;
232 /** flag set when at end of field value block with no TC_ENDBLOCKDATA */
233 private boolean defaultDataEnd = false;
235 /** buffer for reading primitive field values */
236 private byte[] primVals;
238 /** if true, invoke readObjectOverride() instead of readObject() */
239 private final boolean enableOverride;
240 /** if true, invoke resolveObject() */
241 private boolean enableResolve;
244 * Context during upcalls to class-defined readObject methods; holds
245 * object currently being deserialized and descriptor for current class.
246 * Null when not during readObject upcall.
248 private Object curContext;
251 * Creates an ObjectInputStream that reads from the specified InputStream.
252 * A serialization stream header is read from the stream and verified.
253 * This constructor will block until the corresponding ObjectOutputStream
254 * has written and flushed the header.
256 * <p>If a security manager is installed, this constructor will check for
257 * the "enableSubclassImplementation" SerializablePermission when invoked
258 * directly or indirectly by the constructor of a subclass which overrides
259 * the ObjectInputStream.readFields or ObjectInputStream.readUnshared
262 * @param in input stream to read from
263 * @throws StreamCorruptedException if the stream header is incorrect
264 * @throws IOException if an I/O error occurs while reading stream header
265 * @throws SecurityException if untrusted subclass illegally overrides
266 * security-sensitive methods
267 * @throws NullPointerException if <code>in</code> is <code>null</code>
268 * @see ObjectInputStream#ObjectInputStream()
269 * @see ObjectInputStream#readFields()
270 * @see ObjectOutputStream#ObjectOutputStream(OutputStream)
272 public ObjectInputStream(InputStream in) throws IOException {
274 bin = new BlockDataInputStream(in);
275 handles = new HandleTable(10);
276 vlist = new ValidationList();
277 enableOverride = false;
279 bin.setBlockDataMode(true);
283 * Provide a way for subclasses that are completely reimplementing
284 * ObjectInputStream to not have to allocate private data just used by this
285 * implementation of ObjectInputStream.
287 * <p>If there is a security manager installed, this method first calls the
288 * security manager's <code>checkPermission</code> method with the
289 * <code>SerializablePermission("enableSubclassImplementation")</code>
290 * permission to ensure it's ok to enable subclassing.
292 * @throws SecurityException if a security manager exists and its
293 * <code>checkPermission</code> method denies enabling
295 * @see SecurityManager#checkPermission
296 * @see java.io.SerializablePermission
298 protected ObjectInputStream() throws IOException, SecurityException {
299 throw new SecurityException();
303 * Read an object from the ObjectInputStream. The class of the object, the
304 * signature of the class, and the values of the non-transient and
305 * non-static fields of the class and all of its supertypes are read.
306 * Default deserializing for a class can be overriden using the writeObject
307 * and readObject methods. Objects referenced by this object are read
308 * transitively so that a complete equivalent graph of objects is
309 * reconstructed by readObject.
311 * <p>The root object is completely restored when all of its fields and the
312 * objects it references are completely restored. At this point the object
313 * validation callbacks are executed in order based on their registered
314 * priorities. The callbacks are registered by objects (in the readObject
315 * special methods) as they are individually restored.
317 * <p>Exceptions are thrown for problems with the InputStream and for
318 * classes that should not be deserialized. All exceptions are fatal to
319 * the InputStream and leave it in an indeterminate state; it is up to the
320 * caller to ignore or recover the stream state.
322 * @throws ClassNotFoundException Class of a serialized object cannot be
324 * @throws InvalidClassException Something is wrong with a class used by
326 * @throws StreamCorruptedException Control information in the
327 * stream is inconsistent.
328 * @throws OptionalDataException Primitive data was found in the
329 * stream instead of objects.
330 * @throws IOException Any of the usual Input/Output related exceptions.
332 public final Object readObject()
333 throws IOException, ClassNotFoundException
335 throw new IOException();
339 * This method is called by trusted subclasses of ObjectOutputStream that
340 * constructed ObjectOutputStream using the protected no-arg constructor.
341 * The subclass is expected to provide an override method with the modifier
344 * @return the Object read from the stream.
345 * @throws ClassNotFoundException Class definition of a serialized object
347 * @throws OptionalDataException Primitive data was found in the stream
348 * instead of objects.
349 * @throws IOException if I/O errors occurred while reading from the
351 * @see #ObjectInputStream()
355 protected Object readObjectOverride()
356 throws IOException, ClassNotFoundException
362 * Reads an "unshared" object from the ObjectInputStream. This method is
363 * identical to readObject, except that it prevents subsequent calls to
364 * readObject and readUnshared from returning additional references to the
365 * deserialized instance obtained via this call. Specifically:
367 * <li>If readUnshared is called to deserialize a back-reference (the
368 * stream representation of an object which has been written
369 * previously to the stream), an ObjectStreamException will be
372 * <li>If readUnshared returns successfully, then any subsequent attempts
373 * to deserialize back-references to the stream handle deserialized
374 * by readUnshared will cause an ObjectStreamException to be thrown.
376 * Deserializing an object via readUnshared invalidates the stream handle
377 * associated with the returned object. Note that this in itself does not
378 * always guarantee that the reference returned by readUnshared is unique;
379 * the deserialized object may define a readResolve method which returns an
380 * object visible to other parties, or readUnshared may return a Class
381 * object or enum constant obtainable elsewhere in the stream or through
382 * external means. If the deserialized object defines a readResolve method
383 * and the invocation of that method returns an array, then readUnshared
384 * returns a shallow clone of that array; this guarantees that the returned
385 * array object is unique and cannot be obtained a second time from an
386 * invocation of readObject or readUnshared on the ObjectInputStream,
387 * even if the underlying data stream has been manipulated.
389 * <p>ObjectInputStream subclasses which override this method can only be
390 * constructed in security contexts possessing the
391 * "enableSubclassImplementation" SerializablePermission; any attempt to
392 * instantiate such a subclass without this permission will cause a
393 * SecurityException to be thrown.
395 * @return reference to deserialized object
396 * @throws ClassNotFoundException if class of an object to deserialize
398 * @throws StreamCorruptedException if control information in the stream
400 * @throws ObjectStreamException if object to deserialize has already
402 * @throws OptionalDataException if primitive data is next in stream
403 * @throws IOException if an I/O error occurs during deserialization
406 public Object readUnshared() throws IOException, ClassNotFoundException {
407 // if nested read, passHandle contains handle of enclosing object
408 int outerHandle = passHandle;
410 Object obj = readObject0(true);
411 handles.markDependency(outerHandle, passHandle);
412 ClassNotFoundException ex = handles.lookupException(passHandle);
421 passHandle = outerHandle;
422 if (closed && depth == 0) {
429 * Read the non-static and non-transient fields of the current class from
430 * this stream. This may only be called from the readObject method of the
431 * class being deserialized. It will throw the NotActiveException if it is
434 * @throws ClassNotFoundException if the class of a serialized object
435 * could not be found.
436 * @throws IOException if an I/O error occurs.
437 * @throws NotActiveException if the stream is not currently reading
440 public void defaultReadObject()
441 throws IOException, ClassNotFoundException
443 if (curContext == null) {
444 throw new NotActiveException("not in call to readObject");
446 Object curObj = null; // curContext.getObj();
447 ObjectStreamClass curDesc = null; // curContext.getDesc();
448 bin.setBlockDataMode(false);
449 defaultReadFields(curObj, curDesc);
450 bin.setBlockDataMode(true);
451 if (!curDesc.hasWriteObjectData()) {
453 * Fix for 4360508: since stream does not contain terminating
454 * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
455 * knows to simulate end-of-custom-data behavior.
457 defaultDataEnd = true;
459 ClassNotFoundException ex = handles.lookupException(passHandle);
466 * Reads the persistent fields from the stream and makes them available by
469 * @return the <code>GetField</code> object representing the persistent
470 * fields of the object being deserialized
471 * @throws ClassNotFoundException if the class of a serialized object
472 * could not be found.
473 * @throws IOException if an I/O error occurs.
474 * @throws NotActiveException if the stream is not currently reading
478 public ObjectInputStream.GetField readFields()
479 throws IOException, ClassNotFoundException
481 if (curContext == null) {
482 throw new NotActiveException("not in call to readObject");
484 Object curObj = null; // curContext.getObj();
485 ObjectStreamClass curDesc = null; // curContext.getDesc();
486 bin.setBlockDataMode(false);
487 GetFieldImpl getField = new GetFieldImpl(curDesc);
488 getField.readFields();
489 bin.setBlockDataMode(true);
490 if (!curDesc.hasWriteObjectData()) {
492 * Fix for 4360508: since stream does not contain terminating
493 * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
494 * knows to simulate end-of-custom-data behavior.
496 defaultDataEnd = true;
503 * Register an object to be validated before the graph is returned. While
504 * similar to resolveObject these validations are called after the entire
505 * graph has been reconstituted. Typically, a readObject method will
506 * register the object with the stream so that when all of the objects are
507 * restored a final set of validations can be performed.
509 * @param obj the object to receive the validation callback.
510 * @param prio controls the order of callbacks;zero is a good default.
511 * Use higher numbers to be called back earlier, lower numbers for
512 * later callbacks. Within a priority, callbacks are processed in
513 * no particular order.
514 * @throws NotActiveException The stream is not currently reading objects
515 * so it is invalid to register a callback.
516 * @throws InvalidObjectException The validation object is null.
518 public void registerValidation(ObjectInputValidation obj, int prio)
519 throws NotActiveException, InvalidObjectException
522 throw new NotActiveException("stream inactive");
524 vlist.register(obj, prio);
528 * Load the local class equivalent of the specified stream class
529 * description. Subclasses may implement this method to allow classes to
530 * be fetched from an alternate source.
532 * <p>The corresponding method in <code>ObjectOutputStream</code> is
533 * <code>annotateClass</code>. This method will be invoked only once for
534 * each unique class in the stream. This method can be implemented by
535 * subclasses to use an alternate loading mechanism but must return a
536 * <code>Class</code> object. Once returned, if the class is not an array
537 * class, its serialVersionUID is compared to the serialVersionUID of the
538 * serialized class, and if there is a mismatch, the deserialization fails
539 * and an {@link InvalidClassException} is thrown.
541 * <p>The default implementation of this method in
542 * <code>ObjectInputStream</code> returns the result of calling
544 * Class.forName(desc.getName(), false, loader)
546 * where <code>loader</code> is determined as follows: if there is a
547 * method on the current thread's stack whose declaring class was
548 * defined by a user-defined class loader (and was not a generated to
549 * implement reflective invocations), then <code>loader</code> is class
550 * loader corresponding to the closest such method to the currently
551 * executing frame; otherwise, <code>loader</code> is
552 * <code>null</code>. If this call results in a
553 * <code>ClassNotFoundException</code> and the name of the passed
554 * <code>ObjectStreamClass</code> instance is the Java language keyword
555 * for a primitive type or void, then the <code>Class</code> object
556 * representing that primitive type or void will be returned
557 * (e.g., an <code>ObjectStreamClass</code> with the name
558 * <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
559 * Otherwise, the <code>ClassNotFoundException</code> will be thrown to
560 * the caller of this method.
562 * @param desc an instance of class <code>ObjectStreamClass</code>
563 * @return a <code>Class</code> object corresponding to <code>desc</code>
564 * @throws IOException any of the usual Input/Output exceptions.
565 * @throws ClassNotFoundException if class of a serialized object cannot
568 protected Class<?> resolveClass(ObjectStreamClass desc)
569 throws IOException, ClassNotFoundException
571 String name = desc.getName();
573 return Class.forName(name, false, latestUserDefinedLoader());
574 } catch (ClassNotFoundException ex) {
575 Class<?> cl = primClasses.get(name);
585 * Returns a proxy class that implements the interfaces named in a proxy
586 * class descriptor; subclasses may implement this method to read custom
587 * data from the stream along with the descriptors for dynamic proxy
588 * classes, allowing them to use an alternate loading mechanism for the
589 * interfaces and the proxy class.
591 * <p>This method is called exactly once for each unique proxy class
592 * descriptor in the stream.
594 * <p>The corresponding method in <code>ObjectOutputStream</code> is
595 * <code>annotateProxyClass</code>. For a given subclass of
596 * <code>ObjectInputStream</code> that overrides this method, the
597 * <code>annotateProxyClass</code> method in the corresponding subclass of
598 * <code>ObjectOutputStream</code> must write any data or objects read by
601 * <p>The default implementation of this method in
602 * <code>ObjectInputStream</code> returns the result of calling
603 * <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
604 * objects for the interfaces that are named in the <code>interfaces</code>
605 * parameter. The <code>Class</code> object for each interface name
606 * <code>i</code> is the value returned by calling
608 * Class.forName(i, false, loader)
610 * where <code>loader</code> is that of the first non-<code>null</code>
611 * class loader up the execution stack, or <code>null</code> if no
612 * non-<code>null</code> class loaders are on the stack (the same class
613 * loader choice used by the <code>resolveClass</code> method). Unless any
614 * of the resolved interfaces are non-public, this same value of
615 * <code>loader</code> is also the class loader passed to
616 * <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
617 * their class loader is passed instead (if more than one non-public
618 * interface class loader is encountered, an
619 * <code>IllegalAccessError</code> is thrown).
620 * If <code>Proxy.getProxyClass</code> throws an
621 * <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
622 * will throw a <code>ClassNotFoundException</code> containing the
623 * <code>IllegalArgumentException</code>.
625 * @param interfaces the list of interface names that were
626 * deserialized in the proxy class descriptor
627 * @return a proxy class for the specified interfaces
628 * @throws IOException any exception thrown by the underlying
629 * <code>InputStream</code>
630 * @throws ClassNotFoundException if the proxy class or any of the
631 * named interfaces could not be found
632 * @see ObjectOutputStream#annotateProxyClass(Class)
635 protected Class<?> resolveProxyClass(String[] interfaces)
636 throws IOException, ClassNotFoundException
638 ClassLoader latestLoader = latestUserDefinedLoader();
639 ClassLoader nonPublicLoader = null;
640 boolean hasNonPublicInterface = false;
642 // define proxy in class loader of non-public interface(s), if any
643 Class[] classObjs = new Class[interfaces.length];
644 for (int i = 0; i < interfaces.length; i++) {
645 Class cl = Class.forName(interfaces[i], false, latestLoader);
646 if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
647 if (hasNonPublicInterface) {
648 if (nonPublicLoader != cl.getClassLoader()) {
649 throw new IllegalAccessError(
650 "conflicting non-public interface class loaders");
653 nonPublicLoader = cl.getClassLoader();
654 hasNonPublicInterface = true;
660 return Proxy.getProxyClass(
661 hasNonPublicInterface ? nonPublicLoader : latestLoader,
663 } catch (IllegalArgumentException e) {
664 throw new ClassNotFoundException(null, e);
669 * This method will allow trusted subclasses of ObjectInputStream to
670 * substitute one object for another during deserialization. Replacing
671 * objects is disabled until enableResolveObject is called. The
672 * enableResolveObject method checks that the stream requesting to resolve
673 * object can be trusted. Every reference to serializable objects is passed
674 * to resolveObject. To insure that the private state of objects is not
675 * unintentionally exposed only trusted streams may use resolveObject.
677 * <p>This method is called after an object has been read but before it is
678 * returned from readObject. The default resolveObject method just returns
681 * <p>When a subclass is replacing objects it must insure that the
682 * substituted object is compatible with every field where the reference
683 * will be stored. Objects whose type is not a subclass of the type of the
684 * field or array element abort the serialization by raising an exception
685 * and the object is not be stored.
687 * <p>This method is called only once when each object is first
688 * encountered. All subsequent references to the object will be redirected
691 * @param obj object to be substituted
692 * @return the substituted object
693 * @throws IOException Any of the usual Input/Output exceptions.
695 protected Object resolveObject(Object obj) throws IOException {
700 * Enable the stream to allow objects read from the stream to be replaced.
701 * When enabled, the resolveObject method is called for every object being
704 * <p>If <i>enable</i> is true, and there is a security manager installed,
705 * this method first calls the security manager's
706 * <code>checkPermission</code> method with the
707 * <code>SerializablePermission("enableSubstitution")</code> permission to
708 * ensure it's ok to enable the stream to allow objects read from the
709 * stream to be replaced.
711 * @param enable true for enabling use of <code>resolveObject</code> for
712 * every object being deserialized
713 * @return the previous setting before this method was invoked
714 * @throws SecurityException if a security manager exists and its
715 * <code>checkPermission</code> method denies enabling the stream
716 * to allow objects read from the stream to be replaced.
717 * @see SecurityManager#checkPermission
718 * @see java.io.SerializablePermission
720 protected boolean enableResolveObject(boolean enable)
721 throws SecurityException
723 throw new SecurityException();
727 * The readStreamHeader method is provided to allow subclasses to read and
728 * verify their own stream headers. It reads and verifies the magic number
729 * and version number.
731 * @throws IOException if there are I/O errors while reading from the
732 * underlying <code>InputStream</code>
733 * @throws StreamCorruptedException if control information in the stream
736 protected void readStreamHeader()
737 throws IOException, StreamCorruptedException
739 short s0 = bin.readShort();
740 short s1 = bin.readShort();
741 if (s0 != STREAM_MAGIC || s1 != STREAM_VERSION) {
742 throw new StreamCorruptedException(
743 String.format("invalid stream header: %04X%04X", s0, s1));
748 * Read a class descriptor from the serialization stream. This method is
749 * called when the ObjectInputStream expects a class descriptor as the next
750 * item in the serialization stream. Subclasses of ObjectInputStream may
751 * override this method to read in class descriptors that have been written
752 * in non-standard formats (by subclasses of ObjectOutputStream which have
753 * overridden the <code>writeClassDescriptor</code> method). By default,
754 * this method reads class descriptors according to the format defined in
755 * the Object Serialization specification.
757 * @return the class descriptor read
758 * @throws IOException If an I/O error has occurred.
759 * @throws ClassNotFoundException If the Class of a serialized object used
760 * in the class descriptor representation cannot be found
761 * @see java.io.ObjectOutputStream#writeClassDescriptor(java.io.ObjectStreamClass)
764 protected ObjectStreamClass readClassDescriptor()
765 throws IOException, ClassNotFoundException
767 ObjectStreamClass desc = new ObjectStreamClass();
768 desc.readNonProxy(this);
773 * Reads a byte of data. This method will block if no input is available.
775 * @return the byte read, or -1 if the end of the stream is reached.
776 * @throws IOException If an I/O error has occurred.
778 public int read() throws IOException {
783 * Reads into an array of bytes. This method will block until some input
784 * is available. Consider using java.io.DataInputStream.readFully to read
785 * exactly 'length' bytes.
787 * @param buf the buffer into which the data is read
788 * @param off the start offset of the data
789 * @param len the maximum number of bytes read
790 * @return the actual number of bytes read, -1 is returned when the end of
791 * the stream is reached.
792 * @throws IOException If an I/O error has occurred.
793 * @see java.io.DataInputStream#readFully(byte[],int,int)
795 public int read(byte[] buf, int off, int len) throws IOException {
797 throw new NullPointerException();
799 int endoff = off + len;
800 if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
801 throw new IndexOutOfBoundsException();
803 return bin.read(buf, off, len, false);
807 * Returns the number of bytes that can be read without blocking.
809 * @return the number of available bytes.
810 * @throws IOException if there are I/O errors while reading from the
811 * underlying <code>InputStream</code>
813 public int available() throws IOException {
814 return bin.available();
818 * Closes the input stream. Must be called to release any resources
819 * associated with the stream.
821 * @throws IOException If an I/O error has occurred.
823 public void close() throws IOException {
825 * Even if stream already closed, propagate redundant close to
826 * underlying stream to stay consistent with previous implementations.
836 * Reads in a boolean.
838 * @return the boolean read.
839 * @throws EOFException If end of file is reached.
840 * @throws IOException If other I/O error has occurred.
842 public boolean readBoolean() throws IOException {
843 return bin.readBoolean();
847 * Reads an 8 bit byte.
849 * @return the 8 bit byte read.
850 * @throws EOFException If end of file is reached.
851 * @throws IOException If other I/O error has occurred.
853 public byte readByte() throws IOException {
854 return bin.readByte();
858 * Reads an unsigned 8 bit byte.
860 * @return the 8 bit byte read.
861 * @throws EOFException If end of file is reached.
862 * @throws IOException If other I/O error has occurred.
864 public int readUnsignedByte() throws IOException {
865 return bin.readUnsignedByte();
869 * Reads a 16 bit char.
871 * @return the 16 bit char read.
872 * @throws EOFException If end of file is reached.
873 * @throws IOException If other I/O error has occurred.
875 public char readChar() throws IOException {
876 return bin.readChar();
880 * Reads a 16 bit short.
882 * @return the 16 bit short read.
883 * @throws EOFException If end of file is reached.
884 * @throws IOException If other I/O error has occurred.
886 public short readShort() throws IOException {
887 return bin.readShort();
891 * Reads an unsigned 16 bit short.
893 * @return the 16 bit short read.
894 * @throws EOFException If end of file is reached.
895 * @throws IOException If other I/O error has occurred.
897 public int readUnsignedShort() throws IOException {
898 return bin.readUnsignedShort();
902 * Reads a 32 bit int.
904 * @return the 32 bit integer read.
905 * @throws EOFException If end of file is reached.
906 * @throws IOException If other I/O error has occurred.
908 public int readInt() throws IOException {
909 return bin.readInt();
913 * Reads a 64 bit long.
915 * @return the read 64 bit long.
916 * @throws EOFException If end of file is reached.
917 * @throws IOException If other I/O error has occurred.
919 public long readLong() throws IOException {
920 return bin.readLong();
924 * Reads a 32 bit float.
926 * @return the 32 bit float read.
927 * @throws EOFException If end of file is reached.
928 * @throws IOException If other I/O error has occurred.
930 public float readFloat() throws IOException {
931 return bin.readFloat();
935 * Reads a 64 bit double.
937 * @return the 64 bit double read.
938 * @throws EOFException If end of file is reached.
939 * @throws IOException If other I/O error has occurred.
941 public double readDouble() throws IOException {
942 return bin.readDouble();
946 * Reads bytes, blocking until all bytes are read.
948 * @param buf the buffer into which the data is read
949 * @throws EOFException If end of file is reached.
950 * @throws IOException If other I/O error has occurred.
952 public void readFully(byte[] buf) throws IOException {
953 bin.readFully(buf, 0, buf.length, false);
957 * Reads bytes, blocking until all bytes are read.
959 * @param buf the buffer into which the data is read
960 * @param off the start offset of the data
961 * @param len the maximum number of bytes to read
962 * @throws EOFException If end of file is reached.
963 * @throws IOException If other I/O error has occurred.
965 public void readFully(byte[] buf, int off, int len) throws IOException {
966 int endoff = off + len;
967 if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
968 throw new IndexOutOfBoundsException();
970 bin.readFully(buf, off, len, false);
976 * @param len the number of bytes to be skipped
977 * @return the actual number of bytes skipped.
978 * @throws IOException If an I/O error has occurred.
980 public int skipBytes(int len) throws IOException {
981 return bin.skipBytes(len);
985 * Reads in a line that has been terminated by a \n, \r, \r\n or EOF.
987 * @return a String copy of the line.
988 * @throws IOException if there are I/O errors while reading from the
989 * underlying <code>InputStream</code>
990 * @deprecated This method does not properly convert bytes to characters.
991 * see DataInputStream for the details and alternatives.
994 public String readLine() throws IOException {
995 return bin.readLine();
1000 * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
1003 * @return the String.
1004 * @throws IOException if there are I/O errors while reading from the
1005 * underlying <code>InputStream</code>
1006 * @throws UTFDataFormatException if read bytes do not represent a valid
1007 * modified UTF-8 encoding of a string
1009 public String readUTF() throws IOException {
1010 return bin.readUTF();
1014 * Provide access to the persistent fields read from the input stream.
1016 public static abstract class GetField {
1019 * Get the ObjectStreamClass that describes the fields in the stream.
1021 * @return the descriptor class that describes the serializable fields
1023 public abstract ObjectStreamClass getObjectStreamClass();
1026 * Return true if the named field is defaulted and has no value in this
1029 * @param name the name of the field
1030 * @return true, if and only if the named field is defaulted
1031 * @throws IOException if there are I/O errors while reading from
1032 * the underlying <code>InputStream</code>
1033 * @throws IllegalArgumentException if <code>name</code> does not
1034 * correspond to a serializable field
1036 public abstract boolean defaulted(String name) throws IOException;
1039 * Get the value of the named boolean field from the persistent field.
1041 * @param name the name of the field
1042 * @param val the default value to use if <code>name</code> does not
1044 * @return the value of the named <code>boolean</code> field
1045 * @throws IOException if there are I/O errors while reading from the
1046 * underlying <code>InputStream</code>
1047 * @throws IllegalArgumentException if type of <code>name</code> is
1048 * not serializable or if the field type is incorrect
1050 public abstract boolean get(String name, boolean val)
1054 * Get the value of the named byte field from the persistent field.
1056 * @param name the name of the field
1057 * @param val the default value to use if <code>name</code> does not
1059 * @return the value of the named <code>byte</code> field
1060 * @throws IOException if there are I/O errors while reading from the
1061 * underlying <code>InputStream</code>
1062 * @throws IllegalArgumentException if type of <code>name</code> is
1063 * not serializable or if the field type is incorrect
1065 public abstract byte get(String name, byte val) throws IOException;
1068 * Get the value of the named char field from the persistent field.
1070 * @param name the name of the field
1071 * @param val the default value to use if <code>name</code> does not
1073 * @return the value of the named <code>char</code> field
1074 * @throws IOException if there are I/O errors while reading from the
1075 * underlying <code>InputStream</code>
1076 * @throws IllegalArgumentException if type of <code>name</code> is
1077 * not serializable or if the field type is incorrect
1079 public abstract char get(String name, char val) throws IOException;
1082 * Get the value of the named short field from the persistent field.
1084 * @param name the name of the field
1085 * @param val the default value to use if <code>name</code> does not
1087 * @return the value of the named <code>short</code> field
1088 * @throws IOException if there are I/O errors while reading from the
1089 * underlying <code>InputStream</code>
1090 * @throws IllegalArgumentException if type of <code>name</code> is
1091 * not serializable or if the field type is incorrect
1093 public abstract short get(String name, short val) throws IOException;
1096 * Get the value of the named int field from the persistent field.
1098 * @param name the name of the field
1099 * @param val the default value to use if <code>name</code> does not
1101 * @return the value of the named <code>int</code> field
1102 * @throws IOException if there are I/O errors while reading from the
1103 * underlying <code>InputStream</code>
1104 * @throws IllegalArgumentException if type of <code>name</code> is
1105 * not serializable or if the field type is incorrect
1107 public abstract int get(String name, int val) throws IOException;
1110 * Get the value of the named long field from the persistent field.
1112 * @param name the name of the field
1113 * @param val the default value to use if <code>name</code> does not
1115 * @return the value of the named <code>long</code> field
1116 * @throws IOException if there are I/O errors while reading from the
1117 * underlying <code>InputStream</code>
1118 * @throws IllegalArgumentException if type of <code>name</code> is
1119 * not serializable or if the field type is incorrect
1121 public abstract long get(String name, long val) throws IOException;
1124 * Get the value of the named float field from the persistent field.
1126 * @param name the name of the field
1127 * @param val the default value to use if <code>name</code> does not
1129 * @return the value of the named <code>float</code> field
1130 * @throws IOException if there are I/O errors while reading from the
1131 * underlying <code>InputStream</code>
1132 * @throws IllegalArgumentException if type of <code>name</code> is
1133 * not serializable or if the field type is incorrect
1135 public abstract float get(String name, float val) throws IOException;
1138 * Get the value of the named double field from the persistent field.
1140 * @param name the name of the field
1141 * @param val the default value to use if <code>name</code> does not
1143 * @return the value of the named <code>double</code> field
1144 * @throws IOException if there are I/O errors while reading from the
1145 * underlying <code>InputStream</code>
1146 * @throws IllegalArgumentException if type of <code>name</code> is
1147 * not serializable or if the field type is incorrect
1149 public abstract double get(String name, double val) throws IOException;
1152 * Get the value of the named Object field from the persistent field.
1154 * @param name the name of the field
1155 * @param val the default value to use if <code>name</code> does not
1157 * @return the value of the named <code>Object</code> field
1158 * @throws IOException if there are I/O errors while reading from the
1159 * underlying <code>InputStream</code>
1160 * @throws IllegalArgumentException if type of <code>name</code> is
1161 * not serializable or if the field type is incorrect
1163 public abstract Object get(String name, Object val) throws IOException;
1167 * Verifies that this (possibly subclass) instance can be constructed
1168 * without violating security constraints: the subclass must not override
1169 * security-sensitive non-final methods, or else the
1170 * "enableSubclassImplementation" SerializablePermission is checked.
1172 private void verifySubclass() {
1173 Class cl = getClass();
1174 if (cl == ObjectInputStream.class) {
1177 throw new SecurityException();
1181 * Clears internal data structures.
1183 private void clear() {
1189 * Underlying readObject implementation.
1191 private Object readObject0(boolean unshared) throws IOException {
1192 boolean oldMode = bin.getBlockDataMode();
1194 int remain = bin.currentBlockRemaining();
1196 throw new OptionalDataException(remain);
1197 } else if (defaultDataEnd) {
1199 * Fix for 4360508: stream is currently at the end of a field
1200 * value block written via default serialization; since there
1201 * is no terminating TC_ENDBLOCKDATA tag, simulate
1202 * end-of-custom-data behavior explicitly.
1204 throw new OptionalDataException(true);
1206 bin.setBlockDataMode(false);
1210 while ((tc = bin.peekByte()) == TC_RESET) {
1222 return readHandle(unshared);
1225 return readClass(unshared);
1228 case TC_PROXYCLASSDESC:
1229 return readClassDesc(unshared);
1233 return checkResolve(readString(unshared));
1236 return checkResolve(readArray(unshared));
1239 return checkResolve(readEnum(unshared));
1242 return checkResolve(readOrdinaryObject(unshared));
1245 IOException ex = readFatalException();
1246 throw new WriteAbortedException("writing aborted", ex);
1249 case TC_BLOCKDATALONG:
1251 bin.setBlockDataMode(true);
1252 bin.peek(); // force header read
1253 throw new OptionalDataException(
1254 bin.currentBlockRemaining());
1256 throw new StreamCorruptedException(
1257 "unexpected block data");
1260 case TC_ENDBLOCKDATA:
1262 throw new OptionalDataException(true);
1264 throw new StreamCorruptedException(
1265 "unexpected end of block data");
1269 throw new StreamCorruptedException(
1270 String.format("invalid type code: %02X", tc));
1274 bin.setBlockDataMode(oldMode);
1279 * If resolveObject has been enabled and given object does not have an
1280 * exception associated with it, calls resolveObject to determine
1281 * replacement for object, and updates handle table accordingly. Returns
1282 * replacement object, or echoes provided object if no replacement
1283 * occurred. Expects that passHandle is set to given object's handle prior
1284 * to calling this method.
1286 private Object checkResolve(Object obj) throws IOException {
1287 if (!enableResolve || handles.lookupException(passHandle) != null) {
1290 Object rep = resolveObject(obj);
1292 handles.setObject(passHandle, rep);
1298 * Reads string without allowing it to be replaced in stream. Called from
1299 * within ObjectStreamClass.read().
1301 String readTypeString() throws IOException {
1302 int oldHandle = passHandle;
1304 byte tc = bin.peekByte();
1307 return (String) readNull();
1310 return (String) readHandle(false);
1314 return readString(false);
1317 throw new StreamCorruptedException(
1318 String.format("invalid type code: %02X", tc));
1321 passHandle = oldHandle;
1326 * Reads in null code, sets passHandle to NULL_HANDLE and returns null.
1328 private Object readNull() throws IOException {
1329 if (bin.readByte() != TC_NULL) {
1330 throw new InternalError();
1332 passHandle = NULL_HANDLE;
1337 * Reads in object handle, sets passHandle to the read handle, and returns
1338 * object associated with the handle.
1340 private Object readHandle(boolean unshared) throws IOException {
1341 if (bin.readByte() != TC_REFERENCE) {
1342 throw new InternalError();
1344 passHandle = bin.readInt() - baseWireHandle;
1345 if (passHandle < 0 || passHandle >= handles.size()) {
1346 throw new StreamCorruptedException(
1347 String.format("invalid handle value: %08X", passHandle +
1351 // REMIND: what type of exception to throw here?
1352 throw new InvalidObjectException(
1353 "cannot read back reference as unshared");
1356 Object obj = handles.lookupObject(passHandle);
1357 if (obj == unsharedMarker) {
1358 // REMIND: what type of exception to throw here?
1359 throw new InvalidObjectException(
1360 "cannot read back reference to unshared object");
1366 * Reads in and returns class object. Sets passHandle to class object's
1367 * assigned handle. Returns null if class is unresolvable (in which case a
1368 * ClassNotFoundException will be associated with the class' handle in the
1371 private Class readClass(boolean unshared) throws IOException {
1372 if (bin.readByte() != TC_CLASS) {
1373 throw new InternalError();
1375 ObjectStreamClass desc = readClassDesc(false);
1376 Class cl = desc.forClass();
1377 passHandle = handles.assign(unshared ? unsharedMarker : cl);
1379 ClassNotFoundException resolveEx = desc.getResolveException();
1380 if (resolveEx != null) {
1381 handles.markException(passHandle, resolveEx);
1384 handles.finish(passHandle);
1389 * Reads in and returns (possibly null) class descriptor. Sets passHandle
1390 * to class descriptor's assigned handle. If class descriptor cannot be
1391 * resolved to a class in the local VM, a ClassNotFoundException is
1392 * associated with the class descriptor's handle.
1394 private ObjectStreamClass readClassDesc(boolean unshared)
1397 byte tc = bin.peekByte();
1400 return (ObjectStreamClass) readNull();
1403 return (ObjectStreamClass) readHandle(unshared);
1405 case TC_PROXYCLASSDESC:
1406 return readProxyDesc(unshared);
1409 return readNonProxyDesc(unshared);
1412 throw new StreamCorruptedException(
1413 String.format("invalid type code: %02X", tc));
1418 * Reads in and returns class descriptor for a dynamic proxy class. Sets
1419 * passHandle to proxy class descriptor's assigned handle. If proxy class
1420 * descriptor cannot be resolved to a class in the local VM, a
1421 * ClassNotFoundException is associated with the descriptor's handle.
1423 private ObjectStreamClass readProxyDesc(boolean unshared)
1426 if (bin.readByte() != TC_PROXYCLASSDESC) {
1427 throw new InternalError();
1430 ObjectStreamClass desc = new ObjectStreamClass();
1431 int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1432 passHandle = NULL_HANDLE;
1434 int numIfaces = bin.readInt();
1435 String[] ifaces = new String[numIfaces];
1436 for (int i = 0; i < numIfaces; i++) {
1437 ifaces[i] = bin.readUTF();
1441 ClassNotFoundException resolveEx = null;
1442 bin.setBlockDataMode(true);
1444 if ((cl = resolveProxyClass(ifaces)) == null) {
1445 resolveEx = new ClassNotFoundException("null class");
1447 } catch (ClassNotFoundException ex) {
1452 desc.initProxy(cl, resolveEx, readClassDesc(false));
1454 handles.finish(descHandle);
1455 passHandle = descHandle;
1460 * Reads in and returns class descriptor for a class that is not a dynamic
1461 * proxy class. Sets passHandle to class descriptor's assigned handle. If
1462 * class descriptor cannot be resolved to a class in the local VM, a
1463 * ClassNotFoundException is associated with the descriptor's handle.
1465 private ObjectStreamClass readNonProxyDesc(boolean unshared)
1468 if (bin.readByte() != TC_CLASSDESC) {
1469 throw new InternalError();
1472 ObjectStreamClass desc = new ObjectStreamClass();
1473 int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1474 passHandle = NULL_HANDLE;
1476 ObjectStreamClass readDesc = null;
1478 readDesc = readClassDescriptor();
1479 } catch (ClassNotFoundException ex) {
1480 throw (IOException) new InvalidClassException(
1481 "failed to read class descriptor").initCause(ex);
1485 ClassNotFoundException resolveEx = null;
1486 bin.setBlockDataMode(true);
1488 if ((cl = resolveClass(readDesc)) == null) {
1489 resolveEx = new ClassNotFoundException("null class");
1491 } catch (ClassNotFoundException ex) {
1496 desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
1498 handles.finish(descHandle);
1499 passHandle = descHandle;
1504 * Reads in and returns new string. Sets passHandle to new string's
1507 private String readString(boolean unshared) throws IOException {
1509 byte tc = bin.readByte();
1512 str = bin.readUTF();
1516 str = bin.readLongUTF();
1520 throw new StreamCorruptedException(
1521 String.format("invalid type code: %02X", tc));
1523 passHandle = handles.assign(unshared ? unsharedMarker : str);
1524 handles.finish(passHandle);
1529 * Reads in and returns array object, or null if array class is
1530 * unresolvable. Sets passHandle to array's assigned handle.
1532 private Object readArray(boolean unshared) throws IOException {
1533 if (bin.readByte() != TC_ARRAY) {
1534 throw new InternalError();
1537 ObjectStreamClass desc = readClassDesc(false);
1538 int len = bin.readInt();
1540 Object array = null;
1541 Class cl, ccl = null;
1542 if ((cl = desc.forClass()) != null) {
1543 ccl = cl.getComponentType();
1544 array = Array.newInstance(ccl, len);
1547 int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
1548 ClassNotFoundException resolveEx = desc.getResolveException();
1549 if (resolveEx != null) {
1550 handles.markException(arrayHandle, resolveEx);
1554 for (int i = 0; i < len; i++) {
1557 } else if (ccl.isPrimitive()) {
1558 if (ccl == Integer.TYPE) {
1559 bin.readInts((int[]) array, 0, len);
1560 } else if (ccl == Byte.TYPE) {
1561 bin.readFully((byte[]) array, 0, len, true);
1562 } else if (ccl == Long.TYPE) {
1563 bin.readLongs((long[]) array, 0, len);
1564 } else if (ccl == Float.TYPE) {
1565 bin.readFloats((float[]) array, 0, len);
1566 } else if (ccl == Double.TYPE) {
1567 bin.readDoubles((double[]) array, 0, len);
1568 } else if (ccl == Short.TYPE) {
1569 bin.readShorts((short[]) array, 0, len);
1570 } else if (ccl == Character.TYPE) {
1571 bin.readChars((char[]) array, 0, len);
1572 } else if (ccl == Boolean.TYPE) {
1573 bin.readBooleans((boolean[]) array, 0, len);
1575 throw new InternalError();
1578 Object[] oa = (Object[]) array;
1579 for (int i = 0; i < len; i++) {
1580 oa[i] = readObject0(false);
1581 handles.markDependency(arrayHandle, passHandle);
1585 handles.finish(arrayHandle);
1586 passHandle = arrayHandle;
1591 * Reads in and returns enum constant, or null if enum type is
1592 * unresolvable. Sets passHandle to enum constant's assigned handle.
1594 private Enum readEnum(boolean unshared) throws IOException {
1595 if (bin.readByte() != TC_ENUM) {
1596 throw new InternalError();
1599 ObjectStreamClass desc = readClassDesc(false);
1600 if (!desc.isEnum()) {
1601 throw new InvalidClassException("non-enum class: " + desc);
1604 int enumHandle = handles.assign(unshared ? unsharedMarker : null);
1605 ClassNotFoundException resolveEx = desc.getResolveException();
1606 if (resolveEx != null) {
1607 handles.markException(enumHandle, resolveEx);
1610 String name = readString(false);
1612 Class cl = desc.forClass();
1615 en = Enum.valueOf(cl, name);
1616 } catch (IllegalArgumentException ex) {
1617 throw (IOException) new InvalidObjectException(
1618 "enum constant " + name + " does not exist in " +
1622 handles.setObject(enumHandle, en);
1626 handles.finish(enumHandle);
1627 passHandle = enumHandle;
1632 * Reads and returns "ordinary" (i.e., not a String, Class,
1633 * ObjectStreamClass, array, or enum constant) object, or null if object's
1634 * class is unresolvable (in which case a ClassNotFoundException will be
1635 * associated with object's handle). Sets passHandle to object's assigned
1638 private Object readOrdinaryObject(boolean unshared)
1641 if (bin.readByte() != TC_OBJECT) {
1642 throw new InternalError();
1645 ObjectStreamClass desc = readClassDesc(false);
1646 desc.checkDeserialize();
1650 obj = desc.isInstantiable() ? desc.newInstance() : null;
1651 } catch (Exception ex) {
1652 throw (IOException) new InvalidClassException(
1653 desc.forClass().getName(),
1654 "unable to create instance").initCause(ex);
1657 passHandle = handles.assign(unshared ? unsharedMarker : obj);
1658 ClassNotFoundException resolveEx = desc.getResolveException();
1659 if (resolveEx != null) {
1660 handles.markException(passHandle, resolveEx);
1663 if (desc.isExternalizable()) {
1664 readExternalData((Externalizable) obj, desc);
1666 readSerialData(obj, desc);
1669 handles.finish(passHandle);
1672 handles.lookupException(passHandle) == null &&
1673 desc.hasReadResolveMethod())
1675 Object rep = desc.invokeReadResolve(obj);
1676 if (unshared && rep.getClass().isArray()) {
1677 rep = cloneArray(rep);
1680 handles.setObject(passHandle, obj = rep);
1688 * If obj is non-null, reads externalizable data by invoking readExternal()
1689 * method of obj; otherwise, attempts to skip over externalizable data.
1690 * Expects that passHandle is set to obj's handle before this method is
1693 private void readExternalData(Externalizable obj, ObjectStreamClass desc)
1696 Object oldContext = curContext;
1699 boolean blocked = desc.hasBlockExternalData();
1701 bin.setBlockDataMode(true);
1705 obj.readExternal(this);
1706 } catch (ClassNotFoundException ex) {
1708 * In most cases, the handle table has already propagated
1709 * a CNFException to passHandle at this point; this mark
1710 * call is included to address cases where the readExternal
1711 * method has cons'ed and thrown a new CNFException of its
1714 handles.markException(passHandle, ex);
1721 curContext = oldContext;
1724 * At this point, if the externalizable data was not written in
1725 * block-data form and either the externalizable class doesn't exist
1726 * locally (i.e., obj == null) or readExternal() just threw a
1727 * CNFException, then the stream is probably in an inconsistent state,
1728 * since some (or all) of the externalizable data may not have been
1729 * consumed. Since there's no "correct" action to take in this case,
1730 * we mimic the behavior of past serialization implementations and
1731 * blindly hope that the stream is in sync; if it isn't and additional
1732 * externalizable data remains in the stream, a subsequent read will
1733 * most likely throw a StreamCorruptedException.
1738 * Reads (or attempts to skip, if obj is null or is tagged with a
1739 * ClassNotFoundException) instance data for each serializable class of
1740 * object in stream, from superclass to subclass. Expects that passHandle
1741 * is set to obj's handle before this method is called.
1743 private void readSerialData(Object obj, ObjectStreamClass desc)
1746 ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
1747 for (int i = 0; i < slots.length; i++) {
1748 ObjectStreamClass slotDesc = slots[i].desc;
1750 if (slots[i].hasData) {
1752 slotDesc.hasReadObjectMethod() &&
1753 handles.lookupException(passHandle) == null)
1755 Object oldContext = curContext;
1758 curContext = null; //new SerialCallbackContext(obj, slotDesc);
1760 bin.setBlockDataMode(true);
1761 slotDesc.invokeReadObject(obj, this);
1762 } catch (ClassNotFoundException ex) {
1764 * In most cases, the handle table has already
1765 * propagated a CNFException to passHandle at this
1766 * point; this mark call is included to address cases
1767 * where the custom readObject method has cons'ed and
1768 * thrown a new CNFException of its own.
1770 handles.markException(passHandle, ex);
1772 //curContext.setUsed();
1773 curContext = oldContext;
1777 * defaultDataEnd may have been set indirectly by custom
1778 * readObject() method when calling defaultReadObject() or
1779 * readFields(); clear it to restore normal read behavior.
1781 defaultDataEnd = false;
1783 defaultReadFields(obj, slotDesc);
1785 if (slotDesc.hasWriteObjectData()) {
1788 bin.setBlockDataMode(false);
1792 slotDesc.hasReadObjectNoDataMethod() &&
1793 handles.lookupException(passHandle) == null)
1795 slotDesc.invokeReadObjectNoData(obj);
1802 * Skips over all block data and objects until TC_ENDBLOCKDATA is
1805 private void skipCustomData() throws IOException {
1806 int oldHandle = passHandle;
1808 if (bin.getBlockDataMode()) {
1809 bin.skipBlockData();
1810 bin.setBlockDataMode(false);
1812 switch (bin.peekByte()) {
1814 case TC_BLOCKDATALONG:
1815 bin.setBlockDataMode(true);
1818 case TC_ENDBLOCKDATA:
1820 passHandle = oldHandle;
1831 * Reads in values of serializable fields declared by given class
1832 * descriptor. If obj is non-null, sets field values in obj. Expects that
1833 * passHandle is set to obj's handle before this method is called.
1835 private void defaultReadFields(Object obj, ObjectStreamClass desc)
1838 // REMIND: is isInstance check necessary?
1839 Class cl = desc.forClass();
1840 if (cl != null && obj != null && !cl.isInstance(obj)) {
1841 throw new ClassCastException();
1844 int primDataSize = desc.getPrimDataSize();
1845 if (primVals == null || primVals.length < primDataSize) {
1846 primVals = new byte[primDataSize];
1848 bin.readFully(primVals, 0, primDataSize, false);
1850 desc.setPrimFieldValues(obj, primVals);
1853 int objHandle = passHandle;
1854 ObjectStreamField[] fields = desc.getFields(false);
1855 Object[] objVals = new Object[desc.getNumObjFields()];
1856 int numPrimFields = fields.length - objVals.length;
1857 for (int i = 0; i < objVals.length; i++) {
1858 ObjectStreamField f = fields[numPrimFields + i];
1859 objVals[i] = readObject0(f.isUnshared());
1860 if (f.getField() != null) {
1861 handles.markDependency(objHandle, passHandle);
1865 desc.setObjFieldValues(obj, objVals);
1867 passHandle = objHandle;
1871 * Reads in and returns IOException that caused serialization to abort.
1872 * All stream state is discarded prior to reading in fatal exception. Sets
1873 * passHandle to fatal exception's handle.
1875 private IOException readFatalException() throws IOException {
1876 if (bin.readByte() != TC_EXCEPTION) {
1877 throw new InternalError();
1880 return (IOException) readObject0(false);
1884 * If recursion depth is 0, clears internal data structures; otherwise,
1885 * throws a StreamCorruptedException. This method is called when a
1886 * TC_RESET typecode is encountered.
1888 private void handleReset() throws StreamCorruptedException {
1890 throw new StreamCorruptedException(
1891 "unexpected reset; recursion depth: " + depth);
1897 * Converts specified span of bytes into float values.
1899 // REMIND: remove once hotspot inlines Float.intBitsToFloat
1900 private static native void bytesToFloats(byte[] src, int srcpos,
1901 float[] dst, int dstpos,
1905 * Converts specified span of bytes into double values.
1907 // REMIND: remove once hotspot inlines Double.longBitsToDouble
1908 private static native void bytesToDoubles(byte[] src, int srcpos,
1909 double[] dst, int dstpos,
1913 * Returns the first non-null class loader (not counting class loaders of
1914 * generated reflection implementation classes) up the execution stack, or
1915 * null if only code from the null class loader is on the stack. This
1916 * method is also called via reflection by the following RMI-IIOP class:
1918 * com.sun.corba.se.internal.util.JDKClassLoader
1920 * This method should not be removed or its signature changed without
1921 * corresponding modifications to the above class.
1923 // REMIND: change name to something more accurate?
1924 private static native ClassLoader latestUserDefinedLoader();
1927 * Default GetField implementation.
1929 private class GetFieldImpl extends GetField {
1931 /** class descriptor describing serializable fields */
1932 private final ObjectStreamClass desc;
1933 /** primitive field values */
1934 private final byte[] primVals;
1935 /** object field values */
1936 private final Object[] objVals;
1937 /** object field value handles */
1938 private final int[] objHandles;
1941 * Creates GetFieldImpl object for reading fields defined in given
1944 GetFieldImpl(ObjectStreamClass desc) {
1946 primVals = new byte[desc.getPrimDataSize()];
1947 objVals = new Object[desc.getNumObjFields()];
1948 objHandles = new int[objVals.length];
1951 public ObjectStreamClass getObjectStreamClass() {
1955 public boolean defaulted(String name) throws IOException {
1956 return (getFieldOffset(name, null) < 0);
1959 public boolean get(String name, boolean val) throws IOException {
1960 int off = getFieldOffset(name, Boolean.TYPE);
1961 return (off >= 0) ? Bits.getBoolean(primVals, off) : val;
1964 public byte get(String name, byte val) throws IOException {
1965 int off = getFieldOffset(name, Byte.TYPE);
1966 return (off >= 0) ? primVals[off] : val;
1969 public char get(String name, char val) throws IOException {
1970 int off = getFieldOffset(name, Character.TYPE);
1971 return (off >= 0) ? Bits.getChar(primVals, off) : val;
1974 public short get(String name, short val) throws IOException {
1975 int off = getFieldOffset(name, Short.TYPE);
1976 return (off >= 0) ? Bits.getShort(primVals, off) : val;
1979 public int get(String name, int val) throws IOException {
1980 int off = getFieldOffset(name, Integer.TYPE);
1981 return (off >= 0) ? Bits.getInt(primVals, off) : val;
1984 public float get(String name, float val) throws IOException {
1985 int off = getFieldOffset(name, Float.TYPE);
1986 return (off >= 0) ? Bits.getFloat(primVals, off) : val;
1989 public long get(String name, long val) throws IOException {
1990 int off = getFieldOffset(name, Long.TYPE);
1991 return (off >= 0) ? Bits.getLong(primVals, off) : val;
1994 public double get(String name, double val) throws IOException {
1995 int off = getFieldOffset(name, Double.TYPE);
1996 return (off >= 0) ? Bits.getDouble(primVals, off) : val;
1999 public Object get(String name, Object val) throws IOException {
2000 int off = getFieldOffset(name, Object.class);
2002 int objHandle = objHandles[off];
2003 handles.markDependency(passHandle, objHandle);
2004 return (handles.lookupException(objHandle) == null) ?
2005 objVals[off] : null;
2012 * Reads primitive and object field values from stream.
2014 void readFields() throws IOException {
2015 bin.readFully(primVals, 0, primVals.length, false);
2017 int oldHandle = passHandle;
2018 ObjectStreamField[] fields = desc.getFields(false);
2019 int numPrimFields = fields.length - objVals.length;
2020 for (int i = 0; i < objVals.length; i++) {
2022 readObject0(fields[numPrimFields + i].isUnshared());
2023 objHandles[i] = passHandle;
2025 passHandle = oldHandle;
2029 * Returns offset of field with given name and type. A specified type
2030 * of null matches all types, Object.class matches all non-primitive
2031 * types, and any other non-null type matches assignable types only.
2032 * If no matching field is found in the (incoming) class
2033 * descriptor but a matching field is present in the associated local
2034 * class descriptor, returns -1. Throws IllegalArgumentException if
2035 * neither incoming nor local class descriptor contains a match.
2037 private int getFieldOffset(String name, Class type) {
2038 ObjectStreamField field = desc.getField(name, type);
2039 if (field != null) {
2040 return field.getOffset();
2041 } else if (desc.getLocalDesc().getField(name, type) != null) {
2044 throw new IllegalArgumentException("no such field " + name +
2045 " with type " + type);
2051 * Prioritized list of callbacks to be performed once object graph has been
2052 * completely deserialized.
2054 private static class ValidationList {
2058 * Creates new (empty) ValidationList.
2064 * Registers callback. Throws InvalidObjectException if callback
2067 void register(ObjectInputValidation obj, int priority)
2068 throws InvalidObjectException
2071 throw new InvalidObjectException("null callback");
2073 throw new InvalidObjectException("Does not work.");
2077 * Invokes all registered callbacks and clears the callback list.
2078 * Callbacks with higher priorities are called first; those with equal
2079 * priorities may be called in any order. If any of the callbacks
2080 * throws an InvalidObjectException, the callback process is terminated
2081 * and the exception propagated upwards.
2083 void doCallbacks() throws InvalidObjectException {
2087 * Resets the callback list to its initial (empty) state.
2089 public void clear() {
2094 * Input stream supporting single-byte peek operations.
2096 private static class PeekInputStream extends InputStream {
2098 /** underlying stream */
2099 private final InputStream in;
2101 private int peekb = -1;
2104 * Creates new PeekInputStream on top of given underlying stream.
2106 PeekInputStream(InputStream in) {
2111 * Peeks at next byte value in stream. Similar to read(), except
2112 * that it does not consume the read value.
2114 int peek() throws IOException {
2115 return (peekb >= 0) ? peekb : (peekb = in.read());
2118 public int read() throws IOException {
2128 public int read(byte[] b, int off, int len) throws IOException {
2131 } else if (peekb < 0) {
2132 return in.read(b, off, len);
2134 b[off++] = (byte) peekb;
2137 int n = in.read(b, off, len);
2138 return (n >= 0) ? (n + 1) : 1;
2142 void readFully(byte[] b, int off, int len) throws IOException {
2145 int count = read(b, off + n, len - n);
2147 throw new EOFException();
2153 public long skip(long n) throws IOException {
2163 return skipped + skip(n);
2166 public int available() throws IOException {
2167 return in.available() + ((peekb >= 0) ? 1 : 0);
2170 public void close() throws IOException {
2176 * Input stream with two modes: in default mode, inputs data written in the
2177 * same format as DataOutputStream; in "block data" mode, inputs data
2178 * bracketed by block data markers (see object serialization specification
2179 * for details). Buffering depends on block data mode: when in default
2180 * mode, no data is buffered in advance; when in block data mode, all data
2181 * for the current data block is read in at once (and buffered).
2183 private class BlockDataInputStream
2184 extends InputStream implements DataInput
2186 /** maximum data block length */
2187 private static final int MAX_BLOCK_SIZE = 1024;
2188 /** maximum data block header length */
2189 private static final int MAX_HEADER_SIZE = 5;
2190 /** (tunable) length of char buffer (for reading strings) */
2191 private static final int CHAR_BUF_SIZE = 256;
2192 /** readBlockHeader() return value indicating header read may block */
2193 private static final int HEADER_BLOCKED = -2;
2195 /** buffer for reading general/block data */
2196 private final byte[] buf = new byte[MAX_BLOCK_SIZE];
2197 /** buffer for reading block data headers */
2198 private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
2199 /** char buffer for fast string reads */
2200 private final char[] cbuf = new char[CHAR_BUF_SIZE];
2202 /** block data mode */
2203 private boolean blkmode = false;
2205 // block data state fields; values meaningful only when blkmode true
2206 /** current offset into buf */
2207 private int pos = 0;
2208 /** end offset of valid data in buf, or -1 if no more block data */
2209 private int end = -1;
2210 /** number of bytes in current block yet to be read from stream */
2211 private int unread = 0;
2213 /** underlying stream (wrapped in peekable filter stream) */
2214 private final PeekInputStream in;
2215 /** loopback stream (for data reads that span data blocks) */
2216 private final DataInputStream din;
2219 * Creates new BlockDataInputStream on top of given underlying stream.
2220 * Block data mode is turned off by default.
2222 BlockDataInputStream(InputStream in) {
2223 this.in = new PeekInputStream(in);
2224 din = new DataInputStream(this);
2228 * Sets block data mode to the given mode (true == on, false == off)
2229 * and returns the previous mode value. If the new mode is the same as
2230 * the old mode, no action is taken. Throws IllegalStateException if
2231 * block data mode is being switched from on to off while unconsumed
2232 * block data is still present in the stream.
2234 boolean setBlockDataMode(boolean newmode) throws IOException {
2235 if (blkmode == newmode) {
2242 } else if (pos < end) {
2243 throw new IllegalStateException("unread block data");
2250 * Returns true if the stream is currently in block data mode, false
2253 boolean getBlockDataMode() {
2258 * If in block data mode, skips to the end of the current group of data
2259 * blocks (but does not unset block data mode). If not in block data
2260 * mode, throws an IllegalStateException.
2262 void skipBlockData() throws IOException {
2264 throw new IllegalStateException("not in block data mode");
2272 * Attempts to read in the next block data header (if any). If
2273 * canBlock is false and a full header cannot be read without possibly
2274 * blocking, returns HEADER_BLOCKED, else if the next element in the
2275 * stream is a block data header, returns the block data length
2276 * specified by the header, else returns -1.
2278 private int readBlockHeader(boolean canBlock) throws IOException {
2279 if (defaultDataEnd) {
2281 * Fix for 4360508: stream is currently at the end of a field
2282 * value block written via default serialization; since there
2283 * is no terminating TC_ENDBLOCKDATA tag, simulate
2284 * end-of-custom-data behavior explicitly.
2290 int avail = canBlock ? Integer.MAX_VALUE : in.available();
2292 return HEADER_BLOCKED;
2299 return HEADER_BLOCKED;
2301 in.readFully(hbuf, 0, 2);
2302 return hbuf[1] & 0xFF;
2304 case TC_BLOCKDATALONG:
2306 return HEADER_BLOCKED;
2308 in.readFully(hbuf, 0, 5);
2309 int len = Bits.getInt(hbuf, 1);
2311 throw new StreamCorruptedException(
2312 "illegal block data header length: " +
2318 * TC_RESETs may occur in between data blocks.
2319 * Unfortunately, this case must be parsed at a lower
2320 * level than other typecodes, since primitive data
2321 * reads may span data blocks separated by a TC_RESET.
2329 if (tc >= 0 && (tc < TC_BASE || tc > TC_MAX)) {
2330 throw new StreamCorruptedException(
2331 String.format("invalid type code: %02X",
2337 } catch (EOFException ex) {
2338 throw new StreamCorruptedException(
2339 "unexpected EOF while reading block data header");
2344 * Refills internal buffer buf with block data. Any data in buf at the
2345 * time of the call is considered consumed. Sets the pos, end, and
2346 * unread fields to reflect the new amount of available block data; if
2347 * the next element in the stream is not a data block, sets pos and
2348 * unread to 0 and end to -1.
2350 private void refill() throws IOException {
2356 in.read(buf, 0, Math.min(unread, MAX_BLOCK_SIZE));
2361 throw new StreamCorruptedException(
2362 "unexpected EOF in middle of data block");
2365 int n = readBlockHeader(true);
2374 } while (pos == end);
2375 } catch (IOException ex) {
2384 * If in block data mode, returns the number of unconsumed bytes
2385 * remaining in the current data block. If not in block data mode,
2386 * throws an IllegalStateException.
2388 int currentBlockRemaining() {
2390 return (end >= 0) ? (end - pos) + unread : 0;
2392 throw new IllegalStateException();
2397 * Peeks at (but does not consume) and returns the next byte value in
2398 * the stream, or -1 if the end of the stream/block data (if in block
2399 * data mode) has been reached.
2401 int peek() throws IOException {
2406 return (end >= 0) ? (buf[pos] & 0xFF) : -1;
2413 * Peeks at (but does not consume) and returns the next byte value in
2414 * the stream, or throws EOFException if end of stream/block data has
2417 byte peekByte() throws IOException {
2420 throw new EOFException();
2426 /* ----------------- generic input stream methods ------------------ */
2428 * The following methods are equivalent to their counterparts in
2429 * InputStream, except that they interpret data block boundaries and
2430 * read the requested data from within data blocks when in block data
2434 public int read() throws IOException {
2439 return (end >= 0) ? (buf[pos++] & 0xFF) : -1;
2445 public int read(byte[] b, int off, int len) throws IOException {
2446 return read(b, off, len, false);
2449 public long skip(long len) throws IOException {
2451 while (remain > 0) {
2459 int nread = (int) Math.min(remain, end - pos);
2463 int nread = (int) Math.min(remain, MAX_BLOCK_SIZE);
2464 if ((nread = in.read(buf, 0, nread)) < 0) {
2470 return len - remain;
2473 public int available() throws IOException {
2475 if ((pos == end) && (unread == 0)) {
2477 while ((n = readBlockHeader(false)) == 0) ;
2479 case HEADER_BLOCKED:
2494 // avoid unnecessary call to in.available() if possible
2495 int unreadAvail = (unread > 0) ?
2496 Math.min(in.available(), unread) : 0;
2497 return (end >= 0) ? (end - pos) + unreadAvail : 0;
2499 return in.available();
2503 public void close() throws IOException {
2513 * Attempts to read len bytes into byte array b at offset off. Returns
2514 * the number of bytes read, or -1 if the end of stream/block data has
2515 * been reached. If copy is true, reads values into an intermediate
2516 * buffer before copying them to b (to avoid exposing a reference to
2519 int read(byte[] b, int off, int len, boolean copy) throws IOException {
2522 } else if (blkmode) {
2529 int nread = Math.min(len, end - pos);
2530 System.arraycopy(buf, pos, b, off, nread);
2534 int nread = in.read(buf, 0, Math.min(len, MAX_BLOCK_SIZE));
2536 System.arraycopy(buf, 0, b, off, nread);
2540 return in.read(b, off, len);
2544 /* ----------------- primitive data input methods ------------------ */
2546 * The following methods are equivalent to their counterparts in
2547 * DataInputStream, except that they interpret data block boundaries
2548 * and read the requested data from within data blocks when in block
2552 public void readFully(byte[] b) throws IOException {
2553 readFully(b, 0, b.length, false);
2556 public void readFully(byte[] b, int off, int len) throws IOException {
2557 readFully(b, off, len, false);
2560 public void readFully(byte[] b, int off, int len, boolean copy)
2564 int n = read(b, off, len, copy);
2566 throw new EOFException();
2573 public int skipBytes(int n) throws IOException {
2574 return din.skipBytes(n);
2577 public boolean readBoolean() throws IOException {
2580 throw new EOFException();
2585 public byte readByte() throws IOException {
2588 throw new EOFException();
2593 public int readUnsignedByte() throws IOException {
2596 throw new EOFException();
2601 public char readChar() throws IOException {
2604 in.readFully(buf, 0, 2);
2605 } else if (end - pos < 2) {
2606 return din.readChar();
2608 char v = Bits.getChar(buf, pos);
2613 public short readShort() throws IOException {
2616 in.readFully(buf, 0, 2);
2617 } else if (end - pos < 2) {
2618 return din.readShort();
2620 short v = Bits.getShort(buf, pos);
2625 public int readUnsignedShort() throws IOException {
2628 in.readFully(buf, 0, 2);
2629 } else if (end - pos < 2) {
2630 return din.readUnsignedShort();
2632 int v = Bits.getShort(buf, pos) & 0xFFFF;
2637 public int readInt() throws IOException {
2640 in.readFully(buf, 0, 4);
2641 } else if (end - pos < 4) {
2642 return din.readInt();
2644 int v = Bits.getInt(buf, pos);
2649 public float readFloat() throws IOException {
2652 in.readFully(buf, 0, 4);
2653 } else if (end - pos < 4) {
2654 return din.readFloat();
2656 float v = Bits.getFloat(buf, pos);
2661 public long readLong() throws IOException {
2664 in.readFully(buf, 0, 8);
2665 } else if (end - pos < 8) {
2666 return din.readLong();
2668 long v = Bits.getLong(buf, pos);
2673 public double readDouble() throws IOException {
2676 in.readFully(buf, 0, 8);
2677 } else if (end - pos < 8) {
2678 return din.readDouble();
2680 double v = Bits.getDouble(buf, pos);
2685 public String readUTF() throws IOException {
2686 return readUTFBody(readUnsignedShort());
2689 public String readLine() throws IOException {
2690 return din.readLine(); // deprecated, not worth optimizing
2693 /* -------------- primitive data array input methods --------------- */
2695 * The following methods read in spans of primitive data values.
2696 * Though equivalent to calling the corresponding primitive read
2697 * methods repeatedly, these methods are optimized for reading groups
2698 * of primitive data values more efficiently.
2701 void readBooleans(boolean[] v, int off, int len) throws IOException {
2702 int stop, endoff = off + len;
2703 while (off < endoff) {
2705 int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
2706 in.readFully(buf, 0, span);
2709 } else if (end - pos < 1) {
2710 v[off++] = din.readBoolean();
2713 stop = Math.min(endoff, off + end - pos);
2716 while (off < stop) {
2717 v[off++] = Bits.getBoolean(buf, pos++);
2722 void readChars(char[] v, int off, int len) throws IOException {
2723 int stop, endoff = off + len;
2724 while (off < endoff) {
2726 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
2727 in.readFully(buf, 0, span << 1);
2730 } else if (end - pos < 2) {
2731 v[off++] = din.readChar();
2734 stop = Math.min(endoff, off + ((end - pos) >> 1));
2737 while (off < stop) {
2738 v[off++] = Bits.getChar(buf, pos);
2744 void readShorts(short[] v, int off, int len) throws IOException {
2745 int stop, endoff = off + len;
2746 while (off < endoff) {
2748 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 1);
2749 in.readFully(buf, 0, span << 1);
2752 } else if (end - pos < 2) {
2753 v[off++] = din.readShort();
2756 stop = Math.min(endoff, off + ((end - pos) >> 1));
2759 while (off < stop) {
2760 v[off++] = Bits.getShort(buf, pos);
2766 void readInts(int[] v, int off, int len) throws IOException {
2767 int stop, endoff = off + len;
2768 while (off < endoff) {
2770 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
2771 in.readFully(buf, 0, span << 2);
2774 } else if (end - pos < 4) {
2775 v[off++] = din.readInt();
2778 stop = Math.min(endoff, off + ((end - pos) >> 2));
2781 while (off < stop) {
2782 v[off++] = Bits.getInt(buf, pos);
2788 void readFloats(float[] v, int off, int len) throws IOException {
2789 int span, endoff = off + len;
2790 while (off < endoff) {
2792 span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 2);
2793 in.readFully(buf, 0, span << 2);
2795 } else if (end - pos < 4) {
2796 v[off++] = din.readFloat();
2799 span = Math.min(endoff - off, ((end - pos) >> 2));
2802 bytesToFloats(buf, pos, v, off, span);
2808 void readLongs(long[] v, int off, int len) throws IOException {
2809 int stop, endoff = off + len;
2810 while (off < endoff) {
2812 int span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
2813 in.readFully(buf, 0, span << 3);
2816 } else if (end - pos < 8) {
2817 v[off++] = din.readLong();
2820 stop = Math.min(endoff, off + ((end - pos) >> 3));
2823 while (off < stop) {
2824 v[off++] = Bits.getLong(buf, pos);
2830 void readDoubles(double[] v, int off, int len) throws IOException {
2831 int span, endoff = off + len;
2832 while (off < endoff) {
2834 span = Math.min(endoff - off, MAX_BLOCK_SIZE >> 3);
2835 in.readFully(buf, 0, span << 3);
2837 } else if (end - pos < 8) {
2838 v[off++] = din.readDouble();
2841 span = Math.min(endoff - off, ((end - pos) >> 3));
2844 bytesToDoubles(buf, pos, v, off, span);
2851 * Reads in string written in "long" UTF format. "Long" UTF format is
2852 * identical to standard UTF, except that it uses an 8 byte header
2853 * (instead of the standard 2 bytes) to convey the UTF encoding length.
2855 String readLongUTF() throws IOException {
2856 return readUTFBody(readLong());
2860 * Reads in the "body" (i.e., the UTF representation minus the 2-byte
2861 * or 8-byte length header) of a UTF encoding, which occupies the next
2864 private String readUTFBody(long utflen) throws IOException {
2865 StringBuilder sbuf = new StringBuilder();
2870 while (utflen > 0) {
2871 int avail = end - pos;
2872 if (avail >= 3 || (long) avail == utflen) {
2873 utflen -= readUTFSpan(sbuf, utflen);
2876 // near block boundary, read one byte at a time
2877 utflen -= readUTFChar(sbuf, utflen);
2879 // shift and refill buffer manually
2881 System.arraycopy(buf, pos, buf, 0, avail);
2884 end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
2885 in.readFully(buf, avail, end - avail);
2890 return sbuf.toString();
2894 * Reads span of UTF-encoded characters out of internal buffer
2895 * (starting at offset pos and ending at or before offset end),
2896 * consuming no more than utflen bytes. Appends read characters to
2897 * sbuf. Returns the number of bytes consumed.
2899 private long readUTFSpan(StringBuilder sbuf, long utflen)
2904 int avail = Math.min(end - pos, CHAR_BUF_SIZE);
2905 // stop short of last char unless all of utf bytes in buffer
2906 int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
2907 boolean outOfBounds = false;
2910 while (pos < stop) {
2912 b1 = buf[pos++] & 0xFF;
2921 case 7: // 1 byte format: 0xxxxxxx
2922 cbuf[cpos++] = (char) b1;
2926 case 13: // 2 byte format: 110xxxxx 10xxxxxx
2928 if ((b2 & 0xC0) != 0x80) {
2929 throw new UTFDataFormatException();
2931 cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
2932 ((b2 & 0x3F) << 0));
2935 case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
2939 if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
2940 throw new UTFDataFormatException();
2942 cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
2943 ((b2 & 0x3F) << 6) |
2944 ((b3 & 0x3F) << 0));
2947 default: // 10xx xxxx, 1111 xxxx
2948 throw new UTFDataFormatException();
2951 } catch (ArrayIndexOutOfBoundsException ex) {
2954 if (outOfBounds || (pos - start) > utflen) {
2956 * Fix for 4450867: if a malformed utf char causes the
2957 * conversion loop to scan past the expected end of the utf
2958 * string, only consume the expected number of utf bytes.
2960 pos = start + (int) utflen;
2961 throw new UTFDataFormatException();
2965 sbuf.append(cbuf, 0, cpos);
2970 * Reads in single UTF-encoded character one byte at a time, appends
2971 * the character to sbuf, and returns the number of bytes consumed.
2972 * This method is used when reading in UTF strings written in block
2973 * data mode to handle UTF-encoded characters which (potentially)
2974 * straddle block-data boundaries.
2976 private int readUTFChar(StringBuilder sbuf, long utflen)
2980 b1 = readByte() & 0xFF;
2989 case 7: // 1 byte format: 0xxxxxxx
2990 sbuf.append((char) b1);
2994 case 13: // 2 byte format: 110xxxxx 10xxxxxx
2996 throw new UTFDataFormatException();
2999 if ((b2 & 0xC0) != 0x80) {
3000 throw new UTFDataFormatException();
3002 sbuf.append((char) (((b1 & 0x1F) << 6) |
3003 ((b2 & 0x3F) << 0)));
3006 case 14: // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
3009 readByte(); // consume remaining byte
3011 throw new UTFDataFormatException();
3015 if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
3016 throw new UTFDataFormatException();
3018 sbuf.append((char) (((b1 & 0x0F) << 12) |
3019 ((b2 & 0x3F) << 6) |
3020 ((b3 & 0x3F) << 0)));
3023 default: // 10xx xxxx, 1111 xxxx
3024 throw new UTFDataFormatException();
3030 * Unsynchronized table which tracks wire handle to object mappings, as
3031 * well as ClassNotFoundExceptions associated with deserialized objects.
3032 * This class implements an exception-propagation algorithm for
3033 * determining which objects should have ClassNotFoundExceptions associated
3034 * with them, taking into account cycles and discontinuities (e.g., skipped
3035 * fields) in the object graph.
3037 * <p>General use of the table is as follows: during deserialization, a
3038 * given object is first assigned a handle by calling the assign method.
3039 * This method leaves the assigned handle in an "open" state, wherein
3040 * dependencies on the exception status of other handles can be registered
3041 * by calling the markDependency method, or an exception can be directly
3042 * associated with the handle by calling markException. When a handle is
3043 * tagged with an exception, the HandleTable assumes responsibility for
3044 * propagating the exception to any other objects which depend
3045 * (transitively) on the exception-tagged object.
3047 * <p>Once all exception information/dependencies for the handle have been
3048 * registered, the handle should be "closed" by calling the finish method
3049 * on it. The act of finishing a handle allows the exception propagation
3050 * algorithm to aggressively prune dependency links, lessening the
3051 * performance/memory impact of exception tracking.
3053 * <p>Note that the exception propagation algorithm used depends on handles
3054 * being assigned/finished in LIFO order; however, for simplicity as well
3055 * as memory conservation, it does not enforce this constraint.
3057 // REMIND: add full description of exception propagation algorithm?
3058 private static class HandleTable {
3060 /* status codes indicating whether object has associated exception */
3061 private static final byte STATUS_OK = 1;
3062 private static final byte STATUS_UNKNOWN = 2;
3063 private static final byte STATUS_EXCEPTION = 3;
3065 /** array mapping handle -> object status */
3067 /** array mapping handle -> object/exception (depending on status) */
3069 /** array mapping handle -> list of dependent handles (if any) */
3071 /** lowest unresolved dependency */
3073 /** number of handles in table */
3077 * Creates handle table with the given initial capacity.
3079 HandleTable(int initialCapacity) {
3080 status = new byte[initialCapacity];
3081 entries = new Object[initialCapacity];
3082 deps = new HandleList[initialCapacity];
3086 * Assigns next available handle to given object, and returns assigned
3087 * handle. Once object has been completely deserialized (and all
3088 * dependencies on other objects identified), the handle should be
3089 * "closed" by passing it to finish().
3091 int assign(Object obj) {
3092 if (size >= entries.length) {
3095 status[size] = STATUS_UNKNOWN;
3096 entries[size] = obj;
3101 * Registers a dependency (in exception status) of one handle on
3102 * another. The dependent handle must be "open" (i.e., assigned, but
3103 * not finished yet). No action is taken if either dependent or target
3104 * handle is NULL_HANDLE.
3106 void markDependency(int dependent, int target) {
3107 if (dependent == NULL_HANDLE || target == NULL_HANDLE) {
3110 switch (status[dependent]) {
3112 case STATUS_UNKNOWN:
3113 switch (status[target]) {
3115 // ignore dependencies on objs with no exception
3118 case STATUS_EXCEPTION:
3119 // eagerly propagate exception
3120 markException(dependent,
3121 (ClassNotFoundException) entries[target]);
3124 case STATUS_UNKNOWN:
3125 // add to dependency list of target
3126 if (deps[target] == null) {
3127 deps[target] = new HandleList();
3129 deps[target].add(dependent);
3131 // remember lowest unresolved target seen
3132 if (lowDep < 0 || lowDep > target) {
3138 throw new InternalError();
3142 case STATUS_EXCEPTION:
3146 throw new InternalError();
3151 * Associates a ClassNotFoundException (if one not already associated)
3152 * with the currently active handle and propagates it to other
3153 * referencing objects as appropriate. The specified handle must be
3154 * "open" (i.e., assigned, but not finished yet).
3156 void markException(int handle, ClassNotFoundException ex) {
3157 switch (status[handle]) {
3158 case STATUS_UNKNOWN:
3159 status[handle] = STATUS_EXCEPTION;
3160 entries[handle] = ex;
3162 // propagate exception to dependents
3163 HandleList dlist = deps[handle];
3164 if (dlist != null) {
3165 int ndeps = dlist.size();
3166 for (int i = 0; i < ndeps; i++) {
3167 markException(dlist.get(i), ex);
3169 deps[handle] = null;
3173 case STATUS_EXCEPTION:
3177 throw new InternalError();
3182 * Marks given handle as finished, meaning that no new dependencies
3183 * will be marked for handle. Calls to the assign and finish methods
3184 * must occur in LIFO order.
3186 void finish(int handle) {
3189 // no pending unknowns, only resolve current handle
3191 } else if (lowDep >= handle) {
3192 // pending unknowns now clearable, resolve all upward handles
3196 // unresolved backrefs present, can't resolve anything yet
3200 // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
3201 for (int i = handle; i < end; i++) {
3202 switch (status[i]) {
3203 case STATUS_UNKNOWN:
3204 status[i] = STATUS_OK;
3209 case STATUS_EXCEPTION:
3213 throw new InternalError();
3219 * Assigns a new object to the given handle. The object previously
3220 * associated with the handle is forgotten. This method has no effect
3221 * if the given handle already has an exception associated with it.
3222 * This method may be called at any time after the handle is assigned.
3224 void setObject(int handle, Object obj) {
3225 switch (status[handle]) {
3226 case STATUS_UNKNOWN:
3228 entries[handle] = obj;
3231 case STATUS_EXCEPTION:
3235 throw new InternalError();
3240 * Looks up and returns object associated with the given handle.
3241 * Returns null if the given handle is NULL_HANDLE, or if it has an
3242 * associated ClassNotFoundException.
3244 Object lookupObject(int handle) {
3245 return (handle != NULL_HANDLE &&
3246 status[handle] != STATUS_EXCEPTION) ?
3247 entries[handle] : null;
3251 * Looks up and returns ClassNotFoundException associated with the
3252 * given handle. Returns null if the given handle is NULL_HANDLE, or
3253 * if there is no ClassNotFoundException associated with the handle.
3255 ClassNotFoundException lookupException(int handle) {
3256 return (handle != NULL_HANDLE &&
3257 status[handle] == STATUS_EXCEPTION) ?
3258 (ClassNotFoundException) entries[handle] : null;
3262 * Resets table to its initial state.
3265 Arrays.fill(status, 0, size, (byte) 0);
3266 Arrays.fill(entries, 0, size, null);
3267 Arrays.fill(deps, 0, size, null);
3273 * Returns number of handles registered in table.
3280 * Expands capacity of internal arrays.
3282 private void grow() {
3283 int newCapacity = (entries.length << 1) + 1;
3285 byte[] newStatus = new byte[newCapacity];
3286 Object[] newEntries = new Object[newCapacity];
3287 HandleList[] newDeps = new HandleList[newCapacity];
3289 System.arraycopy(status, 0, newStatus, 0, size);
3290 System.arraycopy(entries, 0, newEntries, 0, size);
3291 System.arraycopy(deps, 0, newDeps, 0, size);
3294 entries = newEntries;
3299 * Simple growable list of (integer) handles.
3301 private static class HandleList {
3302 private int[] list = new int[4];
3303 private int size = 0;
3305 public HandleList() {
3308 public void add(int handle) {
3309 if (size >= list.length) {
3310 int[] newList = new int[list.length << 1];
3311 System.arraycopy(list, 0, newList, 0, list.length);
3314 list[size++] = handle;
3317 public int get(int index) {
3318 if (index >= size) {
3319 throw new ArrayIndexOutOfBoundsException();
3331 * Method for cloning arrays in case of using unsharing reading
3333 private static Object cloneArray(Object array) {
3334 if (array instanceof Object[]) {
3335 return ((Object[]) array).clone();
3336 } else if (array instanceof boolean[]) {
3337 return ((boolean[]) array).clone();
3338 } else if (array instanceof byte[]) {
3339 return ((byte[]) array).clone();
3340 } else if (array instanceof char[]) {
3341 return ((char[]) array).clone();
3342 } else if (array instanceof double[]) {
3343 return ((double[]) array).clone();
3344 } else if (array instanceof float[]) {
3345 return ((float[]) array).clone();
3346 } else if (array instanceof int[]) {
3347 return ((int[]) array).clone();
3348 } else if (array instanceof long[]) {
3349 return ((long[]) array).clone();
3350 } else if (array instanceof short[]) {
3351 return ((short[]) array).clone();
3353 throw new AssertionError();