Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Why does Java have transient variables?
I'm working on a Java server that handles a LOT of very dense traffic. The server accepts packets from clients (often many megabytes) and forwards them to other clients. The server never explicitly stores any of the incoming/outgoing packets. Yet the server continually runs into OutOfMemoryException exceptions. I added System.gc() into the message passing component of the server, hoping that m...
Sometimes (quite a lot, actually) we get a situation in Java where two objects are pointing to the same thing. Now if we serialise these separately it is quite appropriate that the serialised forms have separate copies of the object as it should be possible to open one without the other. However if we now deserialise them both, we find that they are still separated. Is there any way to link the...
Just want to know if there's a tutorial or an how-to for serializing object, put it in a stream over network, and deserialize it on the other point. I understand the principles of serialization, I/O, streams, sockets and so on, just want an example (client sending object to a server) to start with. Thank you.
I wonder if it will work... In my app I have an object that I'm serializing to file, and then I obfuscate the code with the ProGuard and application goes to Market. Then I want to release new version of app. I do the same. The users run through the application update. The question is - does the object, that was serialized with the first version of app, deserialize properly in the second one? A...
I'm getting these messages: [#|2010-07-30T11:28:32.723+0000|WARNING|glassfish3.0.1|javax.faces|_ThreadID=37;_ThreadName=Thread-1;|Setting non-serializable attribute value into ViewMap: (key: MyBackingBean, value class: foo.bar.org.jsf.MyBackingBean)|#] Do these mean that my JSF backing beans should implement Serializable? Or are they refering to some other problem?
What are the lightweight options one has to persist Java objects ? I'm looking for the easiest possible solution. I don't want anything fancy featurewise just something simple that works with reasonnably simple objects (some collections, relationships and simple inheritance) and doesn't bring too much apparent complexity (if any) to the existing codebase. The options I'm aware of include Hib...
I have a multi-threaded server that handles client requests, and makes new threads for each one that is connected. This is working great and I am able to send "text" messages back and forth to the server without a problem. Like a chat system. Now I have in mind a way to be able to send files across these client connections to the server, but every single example I see in java always has a hard...
I'm trying to solve a problem I've got on my homework. How can I check if a value is within a range, e.g. 1 ≤ value ≤ 31, without using if, switch, or any other control structure, in Java?
We have this use case where we would like to compress and store objects (in-memory) and decompress them as and when required. The data we want to compress is quite varied, from float vectors to strings to dates. Can someone suggest any good compression technique to do this ? We are looking at ease of compression and speed of decompression as the most important factors. Thanks.
I have two web applications say App1 and App2. I want to call a servlet which is in App2 from a servlet in App1. I'm using URLConnection for this. I'm able to pass parameters to the servlet in App2 also and I'm also able to receive response from the servlet as string. But I want to send java objects from the servlet in App2 and receive them in servlet of App1. How to achieve this?
I have a file that contains java serialized objects like "Vector". I have stored this file over Hadoop Distributed File System(HDFS). Now I intend to read this file (using method readObject) in one of the map task. I suppose FileInputStream in = new FileInputStream("hdfs/path/to/file"); wont' work as the file is stored over HDFS. So I thought of using org.apache.hadoop.fs.FileSystem class. ...
I've started working on some Android applications and have a question regarding how people normally deal with situations where you have a static data set and have an application where that data is needed in memory as one of the standard java collections or as an array. In my current specific issue i have a spreadsheet with some pre-calculated data. It consists of ~100 rows and 3 columns. 1 C...
In an eRCP OSGi based application the user can push a button and go to a lock screen similar to that of Windows or Mac OS X. When this happens, the current state of the application is serialized to a file and control is handed over to the lock screen. In this mobile application memory is very tight, so we need to get rid of the original view/controller when the lock screen comes up. This works...
I'm just learning networking from a java book, so I'm a bit of a noob. I couldn't find this problem in the book or online so I decided to ask the internet. The book says to use the ObjectOutputStream and ObjectInputStream to send and receive objects to different consoles. Now, I'm able to successfully receive the objects I send-- but only once. When I send different objects: random strings an...
snippet from The Server code : public void run() { try { // Create data input and output streams ObjectInputStream inputFromClient = new ObjectInputStream( socket.getInputStream()); ObjectOutputStream outputToClient = new ObjectOutputStream( socket.getOutputStream()); while (true) { cop = inputFromClient.readOb...
i want to cast byte[] which i got from socket a class which I write it (Message). I tried byte[] data=new btyte[100]; . . . Message m=(Message)data; but it did not work and give me error what should I do?
I was handed some data in a file with an .dat extension. I need to read this data in a java program and build the data into some objects we defined. I tried the following, but it did not work FileInputStream fstream = new FileInputStream("news.dat"); DataInputStream in = new DataInputStream(fstream); BufferedReader br = new BufferedReader(new InputStreamReader(in)); Could someone tell me h...
I need to serialize a huge amount of data (around 2gigs) of small objects into a single file in order to be processed later by another Java process. Performance is kind of important. Can anyone suggest a good method to achieve this?
InetAddress host = InetAddress.getLocalHost(); Socket link = new Socket(host, Integer.parseInt(args[0])); System.out.println("before input stream"); ObjectInputStream in = new ObjectInputStream(link.getInputStream()); System.out.println("before output stream"); ObjectInputStream out = new ObjectOutputStream(link.getOutputStream()); "before input stream" is the last lifesign on cmd-line. There...
I want to create own filetype to save objects in my app. Basically, I urgently do not need new filetype, but it will be better. I have class. For example Car. It has constructor (String name, String color, int length, Driver driver). When a car is created (its instance), how to save it like a file?
   /*
    * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    *
    * This code is free software; you can redistribute it and/or modify it
    * under the terms of the GNU General Public License version 2 only, as
    * published by the Free Software Foundation.  Sun designates this
    * particular file as subject to the "Classpath" exception as provided
    * by Sun in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   * CA 95054 USA or visit www.sun.com if you need additional information or
   * have any questions.
   */
  
  package java.io;
  
  import java.util.Arrays;
  import java.util.HashMap;
  import static java.io.ObjectStreamClass.processQueue;

An ObjectInputStream deserializes primitive data and objects previously written using an ObjectOutputStream.

ObjectOutputStream and ObjectInputStream can provide an application with persistent storage for graphs of objects when used with a FileOutputStream and FileInputStream respectively. ObjectInputStream is used to recover those objects previously serialized. Other uses include passing objects between hosts using a socket stream or for marshaling and unmarshaling arguments and parameters in a remote communication system.

ObjectInputStream ensures that the types of all objects in the graph created from the stream match the classes present in the Java Virtual Machine. Classes are loaded as required using the standard mechanisms.

Only objects that support the java.io.Serializable or java.io.Externalizable interface can be read from streams.

The method readObject is used to read an object from the stream. Java's safe casting should be used to get the desired type. In Java, strings and arrays are objects and are treated as objects during serialization. When read they need to be cast to the expected type.

Primitive data types can be read from the stream using the appropriate method on DataInput.

The default deserialization mechanism for objects restores the contents of each field to the value and type it had when it was written. Fields declared as transient or static are ignored by the deserialization process. References to other objects cause those objects to be read from the stream as necessary. Graphs of objects are restored correctly using a reference sharing mechanism. New objects are always allocated when deserializing, which prevents existing objects from being overwritten.

Reading an object is analogous to running the constructors of a new object. Memory is allocated for the object and initialized to zero (NULL). No-arg constructors are invoked for the non-serializable classes and then the fields of the serializable classes are restored from the stream starting with the serializable class closest to java.lang.object and finishing with the object's most specific class.

For example to read from a stream as written by the example in ObjectOutputStream:

      FileInputStream fis = new FileInputStream("t.tmp");
      ObjectInputStream ois = new ObjectInputStream(fis);

      int i = ois.readInt();
      String today = (String) ois.readObject();
      Date date = (Date) ois.readObject();

      ois.close();
 

Classes control how they are serialized by implementing either the java.io.Serializable or java.io.Externalizable interfaces.

Implementing the Serializable interface allows object serialization to save and restore the entire state of the object and it allows classes to evolve between the time the stream is written and the time it is read. It automatically traverses references between objects, saving and restoring entire graphs.

Serializable classes that require special handling during the serialization and deserialization process should implement the following methods:

 private void writeObject(java.io.ObjectOutputStream stream)
     throws IOException;
 private void readObject(java.io.ObjectInputStream stream)
     throws IOException, ClassNotFoundException;
 private void readObjectNoData()
     throws ObjectStreamException;
 

The readObject method is responsible for reading and restoring the state of the object for its particular class using data written to the stream by the corresponding writeObject method. The method does not need to concern itself with the state belonging to its superclasses or subclasses. State is restored by reading data from the ObjectInputStream for the individual fields and making assignments to the appropriate fields of the object. Reading primitive data types is supported by DataInput.

Any attempt to read object data which exceeds the boundaries of the custom data written by the corresponding writeObject method will cause an OptionalDataException to be thrown with an eof field value of true. Non-object reads which exceed the end of the allotted data will reflect the end of data in the same way that they would indicate the end of the stream: bytewise reads will return -1 as the byte read or number of bytes read, and primitive reads will throw EOFExceptions. If there is no corresponding writeObject method, then the end of default serialized data marks the end of the allotted data.

Primitive and object read calls issued from within a readExternal method behave in the same manner--if the stream is already positioned at the end of data written by the corresponding writeExternal method, object reads will throw OptionalDataExceptions with eof set to true, bytewise reads will return -1, and primitive reads will throw EOFExceptions. Note that this behavior does not hold for streams written with the old ObjectStreamConstants.PROTOCOL_VERSION_1 protocol, in which the end of data written by writeExternal methods is not demarcated, and hence cannot be detected.

The readObjectNoData method is responsible for initializing the state of the object for its particular class in the event that the serialization stream does not list the given class as a superclass of the object being deserialized. This may occur in cases where the receiving party uses a different version of the deserialized instance's class than the sending party, and the receiver's version extends classes that are not extended by the sender's version. This may also occur if the serialization stream has been tampered; hence, readObjectNoData is useful for initializing deserialized objects properly despite a "hostile" or incomplete source stream.

Serialization does not read or assign values to the fields of any object that does not implement the java.io.Serializable interface. Subclasses of Objects that are not serializable can be serializable. In this case the non-serializable class must have a no-arg constructor to allow its fields to be initialized. In this case it is the responsibility of the subclass to save and restore the state of the non-serializable class. It is frequently the case that the fields of that class are accessible (public, package, or protected) or that there are get and set methods that can be used to restore the state.

Any exception that occurs while deserializing an object will be caught by the ObjectInputStream and abort the reading process.

Implementing the Externalizable interface allows the object to assume complete control over the contents and format of the object's serialized form. The methods of the Externalizable interface, writeExternal and readExternal, are called to save and restore the objects state. When implemented by a class they can write and read their own state using all of the methods of ObjectOutput and ObjectInput. It is the responsibility of the objects to handle any versioning that occurs.

Enum constants are deserialized differently than ordinary serializable or externalizable objects. The serialized form of an enum constant consists solely of its name; field values of the constant are not transmitted. To deserialize an enum constant, ObjectInputStream reads the constant name from the stream; the deserialized constant is then obtained by calling the static method Enum.valueOf(Class, String) with the enum constant's base type and the received constant name as arguments. Like other serializable or externalizable objects, enum constants can function as the targets of back references appearing subsequently in the serialization stream. The process by which enum constants are deserialized cannot be customized: any class-specific readObject, readObjectNoData, and readResolve methods defined by enum types are ignored during deserialization. Similarly, any serialPersistentFields or serialVersionUID field declarations are also ignored--all enum types have a fixed serialVersionUID of 0L.

Author(s):
Mike Warres
Roger Riggs
Since:
JDK1.1
See also:
DataInput
ObjectOutputStream
Serializable
Object Serialization Specification, Section 3, Object Input Classes
 
 public class ObjectInputStream
     extends InputStream implements ObjectInputObjectStreamConstants
 {
    
handle value representing null
 
     private static final int NULL_HANDLE = -1;

    
marker for unshared objects in internal handle table
 
     private static final Object unsharedMarker = new Object();

    
table mapping primitive type names to corresponding class objects
 
     private static final HashMap primClasses = new HashMap(8, 1.0F);
     static {
         .put("boolean"boolean.class);
         .put("byte"byte.class);
         .put("char"char.class);
         .put("short"short.class);
         .put("int"int.class);
         .put("long"long.class);
         .put("float"float.class);
         .put("double"double.class);
         .put("void"void.class);
     }
 
     private static class Caches {
        
cache of subclass security audit results
 
         static final ConcurrentMap<WeakClassKey,BooleansubclassAudits =
             new ConcurrentHashMap<WeakClassKey,Boolean>();

        
queue for WeakReferences to audited subclasses
 
         static final ReferenceQueue<Class<?>> subclassAuditsQueue =
             new ReferenceQueue<Class<?>>();
     }

    
filter stream for handling block data conversion
 
     private final BlockDataInputStream bin;
    
validation callback list
 
     private final ValidationList vlist;
    
recursion depth
 
     private int depth;
    
whether stream is closed
 
     private boolean closed;

    
wire handle -> obj/exception map
 
     private final HandleTable handles;
    
scratch field for passing handle values up/down call stack
 
     private int passHandle = ;
    
flag set when at end of field value block with no TC_ENDBLOCKDATA
 
     private boolean defaultDataEnd = false;

    
buffer for reading primitive field values
 
     private byte[] primVals;

    
if true, invoke readObjectOverride() instead of readObject()
 
     private final boolean enableOverride;
    
if true, invoke resolveObject()
 
     private boolean enableResolve;

    
Context during upcalls to class-defined readObject methods; holds object currently being deserialized and descriptor for current class. Null when not during readObject upcall.
 
     private CallbackContext curContext;

    
Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the stream and verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.

If a security manager is installed, this constructor will check for the "enableSubclassImplementation" SerializablePermission when invoked directly or indirectly by the constructor of a subclass which overrides the ObjectInputStream.readFields or ObjectInputStream.readUnshared methods.

Parameters:
in input stream to read from
Throws:
StreamCorruptedException if the stream header is incorrect
IOException if an I/O error occurs while reading stream header
java.lang.SecurityException if untrusted subclass illegally overrides security-sensitive methods
java.lang.NullPointerException if in is null
See also:
ObjectInputStream.ObjectInputStream()
readFields()
ObjectOutputStream.ObjectOutputStream.(java.io.OutputStream)
 
     public ObjectInputStream(InputStream inthrows IOException {
         verifySubclass();
          = new BlockDataInputStream(in);
          = new HandleTable(10);
          = new ValidationList();
          = false;
         readStreamHeader();
         .setBlockDataMode(true);
     }

    
Provide a way for subclasses that are completely reimplementing ObjectInputStream to not have to allocate private data just used by this implementation of ObjectInputStream.

If there is a security manager installed, this method first calls the security manager's checkPermission method with the SerializablePermission("enableSubclassImplementation") permission to ensure it's ok to enable subclassing.

Throws:
java.lang.SecurityException if a security manager exists and its checkPermission method denies enabling subclassing.
See also:
java.lang.SecurityManager.checkPermission(java.security.Permission)
SerializablePermission
 
     protected ObjectInputStream() throws IOExceptionSecurityException {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
         }
          = null;
          = null;
          = null;
          = true;
     }

    
Read an object from the ObjectInputStream. The class of the object, the signature of the class, and the values of the non-transient and non-static fields of the class and all of its supertypes are read. Default deserializing for a class can be overriden using the writeObject and readObject methods. Objects referenced by this object are read transitively so that a complete equivalent graph of objects is reconstructed by readObject.

The root object is completely restored when all of its fields and the objects it references are completely restored. At this point the object validation callbacks are executed in order based on their registered priorities. The callbacks are registered by objects (in the readObject special methods) as they are individually restored.

Exceptions are thrown for problems with the InputStream and for classes that should not be deserialized. All exceptions are fatal to the InputStream and leave it in an indeterminate state; it is up to the caller to ignore or recover the stream state.

Throws:
java.lang.ClassNotFoundException Class of a serialized object cannot be found.
InvalidClassException Something is wrong with a class used by serialization.
StreamCorruptedException Control information in the stream is inconsistent.
OptionalDataException Primitive data was found in the stream instead of objects.
IOException Any of the usual Input/Output related exceptions.
 
     public final Object readObject()
         throws IOExceptionClassNotFoundException
     {
         if () {
             return readObjectOverride();
         }
 
         // if nested read, passHandle contains handle of enclosing object
         int outerHandle = ;
         try {
             Object obj = readObject0(false);
             .markDependency(outerHandle);
             ClassNotFoundException ex = .lookupException();
             if (ex != null) {
                 throw ex;
             }
             if ( == 0) {
                 .doCallbacks();
             }
             return obj;
         } finally {
              = outerHandle;
             if ( &&  == 0) {
                 clear();
             }
         }
     }

    
This method is called by trusted subclasses of ObjectOutputStream that constructed ObjectOutputStream using the protected no-arg constructor. The subclass is expected to provide an override method with the modifier "final".

Returns:
the Object read from the stream.
Throws:
java.lang.ClassNotFoundException Class definition of a serialized object cannot be found.
OptionalDataException Primitive data was found in the stream instead of objects.
IOException if I/O errors occurred while reading from the underlying stream
Since:
1.2
See also:
ObjectInputStream()
readObject()
 
     protected Object readObjectOverride()
         throws IOExceptionClassNotFoundException
     {
         return null;
     }

    
Reads an "unshared" object from the ObjectInputStream. This method is identical to readObject, except that it prevents subsequent calls to readObject and readUnshared from returning additional references to the deserialized instance obtained via this call. Specifically:
  • If readUnshared is called to deserialize a back-reference (the stream representation of an object which has been written previously to the stream), an ObjectStreamException will be thrown.
  • If readUnshared returns successfully, then any subsequent attempts to deserialize back-references to the stream handle deserialized by readUnshared will cause an ObjectStreamException to be thrown.
Deserializing an object via readUnshared invalidates the stream handle associated with the returned object. Note that this in itself does not always guarantee that the reference returned by readUnshared is unique; the deserialized object may define a readResolve method which returns an object visible to other parties, or readUnshared may return a Class object or enum constant obtainable elsewhere in the stream or through external means. If the deserialized object defines a readResolve method and the invocation of that method returns an array, then readUnshared returns a shallow clone of that array; this guarantees that the returned array object is unique and cannot be obtained a second time from an invocation of readObject or readUnshared on the ObjectInputStream, even if the underlying data stream has been manipulated.

ObjectInputStream subclasses which override this method can only be constructed in security contexts possessing the "enableSubclassImplementation" SerializablePermission; any attempt to instantiate such a subclass without this permission will cause a SecurityException to be thrown.

Returns:
reference to deserialized object
Throws:
java.lang.ClassNotFoundException if class of an object to deserialize cannot be found
StreamCorruptedException if control information in the stream is inconsistent
ObjectStreamException if object to deserialize has already appeared in stream
OptionalDataException if primitive data is next in stream
IOException if an I/O error occurs during deserialization
Since:
1.4
 
     public Object readUnshared() throws IOExceptionClassNotFoundException {
         // if nested read, passHandle contains handle of enclosing object
         int outerHandle = ;
         try {
             Object obj = readObject0(true);
             .markDependency(outerHandle);
             ClassNotFoundException ex = .lookupException();
             if (ex != null) {
                 throw ex;
             }
             if ( == 0) {
                 .doCallbacks();
             }
             return obj;
         } finally {
              = outerHandle;
             if ( &&  == 0) {
                 clear();
             }
         }
     }

    
Read the non-static and non-transient fields of the current class from this stream. This may only be called from the readObject method of the class being deserialized. It will throw the NotActiveException if it is called otherwise.

Throws:
java.lang.ClassNotFoundException if the class of a serialized object could not be found.
IOException if an I/O error occurs.
NotActiveException if the stream is not currently reading objects.
 
     public void defaultReadObject()
         throws IOExceptionClassNotFoundException
     {
         if ( == null) {
             throw new NotActiveException("not in call to readObject");
         }
         Object curObj = .getObj();
         ObjectStreamClass curDesc = .getDesc();
         .setBlockDataMode(false);
         defaultReadFields(curObjcurDesc);
         .setBlockDataMode(true);
         if (!curDesc.hasWriteObjectData()) {
             /*
              * Fix for 4360508: since stream does not contain terminating
              * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
              * knows to simulate end-of-custom-data behavior.
              */
              = true;
         }
         if (ex != null) {
             throw ex;
         }
     }

    
Reads the persistent fields from the stream and makes them available by name.

Returns:
the GetField object representing the persistent fields of the object being deserialized
Throws:
java.lang.ClassNotFoundException if the class of a serialized object could not be found.
IOException if an I/O error occurs.
NotActiveException if the stream is not currently reading objects.
Since:
1.2
 
         throws IOExceptionClassNotFoundException
     {
         if ( == null) {
             throw new NotActiveException("not in call to readObject");
         }
         Object curObj = .getObj();
         ObjectStreamClass curDesc = .getDesc();
         .setBlockDataMode(false);
         GetFieldImpl getField = new GetFieldImpl(curDesc);
         getField.readFields();
         .setBlockDataMode(true);
         if (!curDesc.hasWriteObjectData()) {
             /*
              * Fix for 4360508: since stream does not contain terminating
              * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
              * knows to simulate end-of-custom-data behavior.
              */
              = true;
         }
 
         return getField;
     }

    
Register an object to be validated before the graph is returned. While similar to resolveObject these validations are called after the entire graph has been reconstituted. Typically, a readObject method will register the object with the stream so that when all of the objects are restored a final set of validations can be performed.

Parameters:
obj the object to receive the validation callback.
prio controls the order of callbacks;zero is a good default. Use higher numbers to be called back earlier, lower numbers for later callbacks. Within a priority, callbacks are processed in no particular order.
Throws:
NotActiveException The stream is not currently reading objects so it is invalid to register a callback.
InvalidObjectException The validation object is null.
 
     public void registerValidation(ObjectInputValidation objint prio)
         throws NotActiveExceptionInvalidObjectException
     {
         if ( == 0) {
             throw new NotActiveException("stream inactive");
         }
         .register(objprio);
     }

    
Load the local class equivalent of the specified stream class description. Subclasses may implement this method to allow classes to be fetched from an alternate source.

The corresponding method in ObjectOutputStream is annotateClass. This method will be invoked only once for each unique class in the stream. This method can be implemented by subclasses to use an alternate loading mechanism but must return a Class object. Once returned, if the class is not an array class, its serialVersionUID is compared to the serialVersionUID of the serialized class, and if there is a mismatch, the deserialization fails and an InvalidClassException is thrown.

The default implementation of this method in ObjectInputStream returns the result of calling

     Class.forName(desc.getName(), false, loader)
 
where loader is determined as follows: if there is a method on the current thread's stack whose declaring class was defined by a user-defined class loader (and was not a generated to implement reflective invocations), then loader is class loader corresponding to the closest such method to the currently executing frame; otherwise, loader is null. If this call results in a ClassNotFoundException and the name of the passed ObjectStreamClass instance is the Java language keyword for a primitive type or void, then the Class object representing that primitive type or void will be returned (e.g., an ObjectStreamClass with the name "int" will be resolved to Integer.TYPE). Otherwise, the ClassNotFoundException will be thrown to the caller of this method.

Parameters:
desc an instance of class ObjectStreamClass
Returns:
a Class object corresponding to desc
Throws:
IOException any of the usual Input/Output exceptions.
java.lang.ClassNotFoundException if class of a serialized object cannot be found.
 
     protected Class<?> resolveClass(ObjectStreamClass desc)
         throws IOExceptionClassNotFoundException
     {
         String name = desc.getName();
         try {
             return Class.forName(namefalselatestUserDefinedLoader());
         } catch (ClassNotFoundException ex) {
             Class cl = (Class.get(name);
             if (cl != null) {
                 return cl;
             } else {
                 throw ex;
             }
         }
     }

    
Returns a proxy class that implements the interfaces named in a proxy class descriptor; subclasses may implement this method to read custom data from the stream along with the descriptors for dynamic proxy classes, allowing them to use an alternate loading mechanism for the interfaces and the proxy class.

This method is called exactly once for each unique proxy class descriptor in the stream.

The corresponding method in ObjectOutputStream is annotateProxyClass. For a given subclass of ObjectInputStream that overrides this method, the annotateProxyClass method in the corresponding subclass of ObjectOutputStream must write any data or objects read by this method.

The default implementation of this method in ObjectInputStream returns the result of calling Proxy.getProxyClass with the list of Class objects for the interfaces that are named in the interfaces parameter. The Class object for each interface name i is the value returned by calling

     Class.forName(i, false, loader)
 
where loader is that of the first non-null class loader up the execution stack, or null if no non-null class loaders are on the stack (the same class loader choice used by the resolveClass method). Unless any of the resolved interfaces are non-public, this same value of loader is also the class loader passed to Proxy.getProxyClass; if non-public interfaces are present, their class loader is passed instead (if more than one non-public interface class loader is encountered, an IllegalAccessError is thrown). If Proxy.getProxyClass throws an IllegalArgumentException, resolveProxyClass will throw a ClassNotFoundException containing the IllegalArgumentException.

Parameters:
interfaces the list of interface names that were deserialized in the proxy class descriptor
Returns:
a proxy class for the specified interfaces
Throws:
IOException any exception thrown by the underlying InputStream
java.lang.ClassNotFoundException if the proxy class or any of the named interfaces could not be found
Since:
1.3
See also:
ObjectOutputStream.annotateProxyClass(java.lang.Class)
 
     protected Class<?> resolveProxyClass(String[] interfaces)
         throws IOExceptionClassNotFoundException
     {
         ClassLoader latestLoader = latestUserDefinedLoader();
         ClassLoader nonPublicLoader = null;
         boolean hasNonPublicInterface = false;
 
         // define proxy in class loader of non-public interface(s), if any
         Class[] classObjs = new Class[interfaces.length];
         for (int i = 0; i < interfaces.lengthi++) {
             Class cl = Class.forName(interfaces[i], falselatestLoader);
             if ((cl.getModifiers() & .) == 0) {
                 if (hasNonPublicInterface) {
                     if (nonPublicLoader != cl.getClassLoader()) {
                         throw new IllegalAccessError(
                             "conflicting non-public interface class loaders");
                     }
                 } else {
                     nonPublicLoader = cl.getClassLoader();
                     hasNonPublicInterface = true;
                 }
             }
             classObjs[i] = cl;
         }
         try {
             return Proxy.getProxyClass(
                 hasNonPublicInterface ? nonPublicLoader : latestLoader,
                 classObjs);
         } catch (IllegalArgumentException e) {
             throw new ClassNotFoundException(nulle);
         }
     }

    
This method will allow trusted subclasses of ObjectInputStream to substitute one object for another during deserialization. Replacing objects is disabled until enableResolveObject is called. The enableResolveObject method checks that the stream requesting to resolve object can be trusted. Every reference to serializable objects is passed to resolveObject. To insure that the private state of objects is not unintentionally exposed only trusted streams may use resolveObject.

This method is called after an object has been read but before it is returned from readObject. The default resolveObject method just returns the same object.

When a subclass is replacing objects it must insure that the substituted object is compatible with every field where the reference will be stored. Objects whose type is not a subclass of the type of the field or array element abort the serialization by raising an exception and the object is not be stored.

This method is called only once when each object is first encountered. All subsequent references to the object will be redirected to the new object.

Parameters:
obj object to be substituted
Returns:
the substituted object
Throws:
IOException Any of the usual Input/Output exceptions.
 
     protected Object resolveObject(Object objthrows IOException {
         return obj;
     }

    
Enable the stream to allow objects read from the stream to be replaced. When enabled, the resolveObject method is called for every object being deserialized.

If enable is true, and there is a security manager installed, this method first calls the security manager's checkPermission method with the SerializablePermission("enableSubstitution") permission to ensure it's ok to enable the stream to allow objects read from the stream to be replaced.

Parameters:
enable true for enabling use of resolveObject for every object being deserialized
Returns:
the previous setting before this method was invoked
Throws:
java.lang.SecurityException if a security manager exists and its checkPermission method denies enabling the stream to allow objects read from the stream to be replaced.
See also:
java.lang.SecurityManager.checkPermission(java.security.Permission)
SerializablePermission
 
     protected boolean enableResolveObject(boolean enable)
         throws SecurityException
     {
         if (enable == ) {
             return enable;
         }
         if (enable) {
             SecurityManager sm = System.getSecurityManager();
             if (sm != null) {
                 sm.checkPermission();
             }
         }
          = enable;
         return !;
     }

    
The readStreamHeader method is provided to allow subclasses to read and verify their own stream headers. It reads and verifies the magic number and version number.

Throws:
IOException if there are I/O errors while reading from the underlying InputStream
StreamCorruptedException if control information in the stream is inconsistent
 
     protected void readStreamHeader()
         throws IOExceptionStreamCorruptedException
     {
         short s0 = .readShort();
         short s1 = .readShort();
         if (s0 !=  || s1 != ) {
             throw new StreamCorruptedException(
                 String.format("invalid stream header: %04X%04X"s0s1));
         }
     }

    
Read a class descriptor from the serialization stream. This method is called when the ObjectInputStream expects a class descriptor as the next item in the serialization stream. Subclasses of ObjectInputStream may override this method to read in class descriptors that have been written in non-standard formats (by subclasses of ObjectOutputStream which have overridden the writeClassDescriptor method). By default, this method reads class descriptors according to the format defined in the Object Serialization specification.

Returns:
the class descriptor read
Throws:
IOException If an I/O error has occurred.
java.lang.ClassNotFoundException If the Class of a serialized object used in the class descriptor representation cannot be found
Since:
1.3
See also:
ObjectOutputStream.writeClassDescriptor(java.io.ObjectStreamClass)
 
         throws IOExceptionClassNotFoundException
     {
         ObjectStreamClass desc = new ObjectStreamClass();
         desc.readNonProxy(this);
         return desc;
     }

    
Reads a byte of data. This method will block if no input is available.

Returns:
the byte read, or -1 if the end of the stream is reached.
Throws:
IOException If an I/O error has occurred.
 
     public int read() throws IOException {
         return .read();
     }

    
Reads into an array of bytes. This method will block until some input is available. Consider using java.io.DataInputStream.readFully to read exactly 'length' bytes.

Parameters:
buf the buffer into which the data is read
off the start offset of the data
len the maximum number of bytes read
Returns:
the actual number of bytes read, -1 is returned when the end of the stream is reached.
Throws:
IOException If an I/O error has occurred.
See also:
DataInputStream.readFully(byte[],int,int)
 
     public int read(byte[] bufint offint lenthrows IOException {
         if (buf == null) {
             throw new NullPointerException();
         }
         int endoff = off + len;
         if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
             throw new IndexOutOfBoundsException();
         }
         return .read(bufofflenfalse);
     }

    
Returns the number of bytes that can be read without blocking.

Returns:
the number of available bytes.
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
 
     public int available() throws IOException {
         return .available();
     }

    
Closes the input stream. Must be called to release any resources associated with the stream.

Throws:
IOException If an I/O error has occurred.
 
     public void close() throws IOException {
         /*
          * Even if stream already closed, propagate redundant close to
          * underlying stream to stay consistent with previous implementations.
          */
          = true;
         if ( == 0) {
             clear();
         }
         .close();
     }

    
Reads in a boolean.

Returns:
the boolean read.
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
 
     public boolean readBoolean() throws IOException {
         return .readBoolean();
     }

    
Reads an 8 bit byte.

Returns:
the 8 bit byte read.
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
 
     public byte readByte() throws IOException  {
         return .readByte();
     }

    
Reads an unsigned 8 bit byte.

Returns:
the 8 bit byte read.
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
 
     public int readUnsignedByte()  throws IOException {
         return .readUnsignedByte();
     }

    
Reads a 16 bit char.

Returns:
the 16 bit char read.
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
 
     public char readChar()  throws IOException {
         return .readChar();
     }

    
Reads a 16 bit short.

Returns:
the 16 bit short read.
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
 
     public short readShort()  throws IOException {
         return .readShort();
     }

    
Reads an unsigned 16 bit short.

Returns:
the 16 bit short read.
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
 
     public int readUnsignedShort() throws IOException {
         return .readUnsignedShort();
     }

    
Reads a 32 bit int.

Returns:
the 32 bit integer read.
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
 
     public int readInt()  throws IOException {
         return .readInt();
     }

    
Reads a 64 bit long.

Returns:
the read 64 bit long.
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
 
     public long readLong()  throws IOException {
         return .readLong();
     }

    
Reads a 32 bit float.

Returns:
the 32 bit float read.
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
 
     public float readFloat() throws IOException {
         return .readFloat();
     }

    
Reads a 64 bit double.

Returns:
the 64 bit double read.
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
 
     public double readDouble() throws IOException {
        return .readDouble();
    }

    
Reads bytes, blocking until all bytes are read.

Parameters:
buf the buffer into which the data is read
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
    public void readFully(byte[] bufthrows IOException {
        .readFully(buf, 0, buf.lengthfalse);
    }

    
Reads bytes, blocking until all bytes are read.

Parameters:
buf the buffer into which the data is read
off the start offset of the data
len the maximum number of bytes to read
Throws:
EOFException If end of file is reached.
IOException If other I/O error has occurred.
    public void readFully(byte[] bufint offint lenthrows IOException {
        int endoff = off + len;
        if (off < 0 || len < 0 || endoff > buf.length || endoff < 0) {
            throw new IndexOutOfBoundsException();
        }
        .readFully(bufofflenfalse);
    }

    
Skips bytes.

Parameters:
len the number of bytes to be skipped
Returns:
the actual number of bytes skipped.
Throws:
IOException If an I/O error has occurred.
    public int skipBytes(int lenthrows IOException {
        return .skipBytes(len);
    }

    
Reads in a line that has been terminated by a \n, \r, \r\n or EOF.

Deprecated:
This method does not properly convert bytes to characters. see DataInputStream for the details and alternatives.
Returns:
a String copy of the line.
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
    public String readLine() throws IOException {
        return .readLine();
    }

    
Reads a String in modified UTF-8 format.

Returns:
the String.
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
UTFDataFormatException if read bytes do not represent a valid modified UTF-8 encoding of a string
    public String readUTF() throws IOException {
        return .readUTF();
    }

    
Provide access to the persistent fields read from the input stream.
    public static abstract class GetField {

        
Get the ObjectStreamClass that describes the fields in the stream.

Returns:
the descriptor class that describes the serializable fields
        public abstract ObjectStreamClass getObjectStreamClass();

        
Return true if the named field is defaulted and has no value in this stream.

Parameters:
name the name of the field
Returns:
true, if and only if the named field is defaulted
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
java.lang.IllegalArgumentException if name does not correspond to a serializable field
        public abstract boolean defaulted(String namethrows IOException;

        
Get the value of the named boolean field from the persistent field.

Parameters:
name the name of the field
val the default value to use if name does not have a value
Returns:
the value of the named boolean field
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
java.lang.IllegalArgumentException if type of name is not serializable or if the field type is incorrect
        public abstract boolean get(String nameboolean val)
            throws IOException;

        
Get the value of the named byte field from the persistent field.

Parameters:
name the name of the field
val the default value to use if name does not have a value
Returns:
the value of the named byte field
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
java.lang.IllegalArgumentException if type of name is not serializable or if the field type is incorrect
        public abstract byte get(String namebyte valthrows IOException;

        
Get the value of the named char field from the persistent field.

Parameters:
name the name of the field
val the default value to use if name does not have a value
Returns:
the value of the named char field
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
java.lang.IllegalArgumentException if type of name is not serializable or if the field type is incorrect
        public abstract char get(String namechar valthrows IOException;

        
Get the value of the named short field from the persistent field.

Parameters:
name the name of the field
val the default value to use if name does not have a value
Returns:
the value of the named short field
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
java.lang.IllegalArgumentException if type of name is not serializable or if the field type is incorrect
        public abstract short get(String nameshort valthrows IOException;

        
Get the value of the named int field from the persistent field.

Parameters:
name the name of the field
val the default value to use if name does not have a value
Returns:
the value of the named int field
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
java.lang.IllegalArgumentException if type of name is not serializable or if the field type is incorrect
        public abstract int get(String nameint valthrows IOException;

        
Get the value of the named long field from the persistent field.

Parameters:
name the name of the field
val the default value to use if name does not have a value
Returns:
the value of the named long field
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
java.lang.IllegalArgumentException if type of name is not serializable or if the field type is incorrect
        public abstract long get(String namelong valthrows IOException;

        
Get the value of the named float field from the persistent field.

Parameters:
name the name of the field
val the default value to use if name does not have a value
Returns:
the value of the named float field
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
java.lang.IllegalArgumentException if type of name is not serializable or if the field type is incorrect
        public abstract float get(String namefloat valthrows IOException;

        
Get the value of the named double field from the persistent field.

Parameters:
name the name of the field
val the default value to use if name does not have a value
Returns:
the value of the named double field
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
java.lang.IllegalArgumentException if type of name is not serializable or if the field type is incorrect
        public abstract double get(String namedouble valthrows IOException;

        
Get the value of the named Object field from the persistent field.

Parameters:
name the name of the field
val the default value to use if name does not have a value
Returns:
the value of the named Object field
Throws:
IOException if there are I/O errors while reading from the underlying InputStream
java.lang.IllegalArgumentException if type of name is not serializable or if the field type is incorrect
        public abstract Object get(String nameObject valthrows IOException;
    }

    
Verifies that this (possibly subclass) instance can be constructed without violating security constraints: the subclass must not override security-sensitive non-final methods, or else the "enableSubclassImplementation" SerializablePermission is checked.
    private void verifySubclass() {
        Class cl = getClass();
        if (cl == ObjectInputStream.class) {
            return;
        }
        SecurityManager sm = System.getSecurityManager();
        if (sm == null) {
            return;
        }
        WeakClassKey key = new WeakClassKey(cl.);
        Boolean result = ..get(key);
        if (result == null) {
            result = Boolean.valueOf(auditSubclass(cl));
            ..putIfAbsent(keyresult);
        }
        if (result.booleanValue()) {
            return;
        }
    }

    
Performs reflective checks on given subclass to verify that it doesn't override security-sensitive non-final methods. Returns true if subclass is "safe", false otherwise.
    private static boolean auditSubclass(final Class subcl) {
        Boolean result = AccessController.doPrivileged(
            new PrivilegedAction<Boolean>() {
                public Boolean run() {
                    for (Class cl = subcl;
                         cl != ObjectInputStream.class;
                         cl = cl.getSuperclass())
                    {
                        try {
                            cl.getDeclaredMethod(
                                "readUnshared", (Class[]) null);
                            return .;
                        } catch (NoSuchMethodException ex) {
                        }
                        try {
                            cl.getDeclaredMethod("readFields", (Class[]) null);
                            return .;
                        } catch (NoSuchMethodException ex) {
                        }
                    }
                    return .;
                }
            }
        );
        return result.booleanValue();
    }

    
Clears internal data structures.
    private void clear() {
        .clear();
        .clear();
    }

    
Underlying readObject implementation.
    private Object readObject0(boolean unsharedthrows IOException {
        boolean oldMode = .getBlockDataMode();
        if (oldMode) {
            int remain = .currentBlockRemaining();
            if (remain > 0) {
                throw new OptionalDataException(remain);
            } else if () {
                /*
                 * Fix for 4360508: stream is currently at the end of a field
                 * value block written via default serialization; since there
                 * is no terminating TC_ENDBLOCKDATA tag, simulate
                 * end-of-custom-data behavior explicitly.
                 */
                throw new OptionalDataException(true);
            }
            .setBlockDataMode(false);
        }
        byte tc;
        while ((tc = .peekByte()) == ) {
            .readByte();
            handleReset();
        }
        ++;
        try {
            switch (tc) {
                case :
                    return readNull();
                case :
                    return readHandle(unshared);
                case :
                    return readClass(unshared);
                case :
                case :
                    return readClassDesc(unshared);
                case :
                case :
                    return checkResolve(readString(unshared));
                case :
                    return checkResolve(readArray(unshared));
                case :
                    return checkResolve(readEnum(unshared));
                case :
                    return checkResolve(readOrdinaryObject(unshared));
                case :
                    IOException ex = readFatalException();
                    throw new WriteAbortedException("writing aborted"ex);
                case :
                case :
                    if (oldMode) {
                        .setBlockDataMode(true);
                        .peek();             // force header read
                        throw new OptionalDataException(
                            .currentBlockRemaining());
                    } else {
                        throw new StreamCorruptedException(
                            "unexpected block data");
                    }
                case :
                    if (oldMode) {
                        throw new OptionalDataException(true);
                    } else {
                        throw new StreamCorruptedException(
                            "unexpected end of block data");
                    }
                default:
                    throw new StreamCorruptedException(
                        String.format("invalid type code: %02X"tc));
            }
        } finally {
            --;
            .setBlockDataMode(oldMode);
        }
    }

    
If resolveObject has been enabled and given object does not have an exception associated with it, calls resolveObject to determine replacement for object, and updates handle table accordingly. Returns replacement object, or echoes provided object if no replacement occurred. Expects that passHandle is set to given object's handle prior to calling this method.
    private Object checkResolve(Object objthrows IOException {
        if (! || .lookupException() != null) {
            return obj;
        }
        Object rep = resolveObject(obj);
        if (rep != obj) {
            .setObject(rep);
        }
        return rep;
    }

    
Reads string without allowing it to be replaced in stream. Called from within ObjectStreamClass.read().
    String readTypeString() throws IOException {
        int oldHandle = ;
        try {
            byte tc = .peekByte();
            switch (tc) {
                case :
                    return (StringreadNull();
                case :
                    return (StringreadHandle(false);
                case :
                case :
                    return readString(false);
                default:
                    throw new StreamCorruptedException(
                        String.format("invalid type code: %02X"tc));
            }
        } finally {
             = oldHandle;
        }
    }

    
Reads in null code, sets passHandle to NULL_HANDLE and returns null.
    private Object readNull() throws IOException {
        if (.readByte() != ) {
            throw new InternalError();
        }
         = ;
        return null;
    }

    
Reads in object handle, sets passHandle to the read handle, and returns object associated with the handle.
    private Object readHandle(boolean unsharedthrows IOException {
        if (.readByte() != ) {
            throw new InternalError();
        }
         = .readInt() - ;
        if ( < 0 ||  >= .size()) {
            throw new StreamCorruptedException(
                String.format("invalid handle value: %08X" +
                ));
        }
        if (unshared) {
            // REMIND: what type of exception to throw here?
            throw new InvalidObjectException(
                "cannot read back reference as unshared");
        }
        Object obj = .lookupObject();
        if (obj == ) {
            // REMIND: what type of exception to throw here?
            throw new InvalidObjectException(
                "cannot read back reference to unshared object");
        }
        return obj;
    }

    
Reads in and returns class object. Sets passHandle to class object's assigned handle. Returns null if class is unresolvable (in which case a ClassNotFoundException will be associated with the class' handle in the handle table).
    private Class readClass(boolean unsharedthrows IOException {
        if (.readByte() != ) {
            throw new InternalError();
        }
        ObjectStreamClass desc = readClassDesc(false);
        Class cl = desc.forClass();
         = .assign(unshared ?  : cl);
        ClassNotFoundException resolveEx = desc.getResolveException();
        if (resolveEx != null) {
            .markException(resolveEx);
        }
        .finish();
        return cl;
    }

    
Reads in and returns (possibly null) class descriptor. Sets passHandle to class descriptor's assigned handle. If class descriptor cannot be resolved to a class in the local VM, a ClassNotFoundException is associated with the class descriptor's handle.
    private ObjectStreamClass readClassDesc(boolean unshared)
        throws IOException
    {
        byte tc = .peekByte();
        switch (tc) {
            case :
                return (ObjectStreamClassreadNull();
            case :
                return (ObjectStreamClassreadHandle(unshared);
            case :
                return readProxyDesc(unshared);
            case :
                return readNonProxyDesc(unshared);
            default:
                throw new StreamCorruptedException(
                    String.format("invalid type code: %02X"tc));
        }
    }

    
Reads in and returns class descriptor for a dynamic proxy class. Sets passHandle to proxy class descriptor's assigned handle. If proxy class descriptor cannot be resolved to a class in the local VM, a ClassNotFoundException is associated with the descriptor's handle.
    private ObjectStreamClass readProxyDesc(boolean unshared)
        throws IOException
    {
        if (.readByte() != ) {
            throw new InternalError();
        }
        ObjectStreamClass desc = new ObjectStreamClass();
        int descHandle = .assign(unshared ?  : desc);
         = ;
        int numIfaces = .readInt();
        String[] ifaces = new String[numIfaces];
        for (int i = 0; i < numIfacesi++) {
            ifaces[i] = .readUTF();
        }
        Class cl = null;
        ClassNotFoundException resolveEx = null;
        .setBlockDataMode(true);
        try {
            if ((cl = resolveProxyClass(ifaces)) == null) {
                resolveEx = new ClassNotFoundException("null class");
            }
        } catch (ClassNotFoundException ex) {
            resolveEx = ex;
        }
        skipCustomData();
        desc.initProxy(clresolveExreadClassDesc(false));
        .finish(descHandle);
         = descHandle;
        return desc;
    }

    
Reads in and returns class descriptor for a class that is not a dynamic proxy class. Sets passHandle to class descriptor's assigned handle. If class descriptor cannot be resolved to a class in the local VM, a ClassNotFoundException is associated with the descriptor's handle.
    private ObjectStreamClass readNonProxyDesc(boolean unshared)
        throws IOException
    {
        if (.readByte() != ) {
            throw new InternalError();
        }
        ObjectStreamClass desc = new ObjectStreamClass();
        int descHandle = .assign(unshared ?  : desc);
         = ;
        ObjectStreamClass readDesc = null;
        try {
            readDesc = readClassDescriptor();
        } catch (ClassNotFoundException ex) {
            throw (IOExceptionnew InvalidClassException(
                "failed to read class descriptor").initCause(ex);
        }
        Class cl = null;
        ClassNotFoundException resolveEx = null;
        .setBlockDataMode(true);
        try {
            if ((cl = resolveClass(readDesc)) == null) {
                resolveEx = new ClassNotFoundException("null class");
            }
        } catch (ClassNotFoundException ex) {
            resolveEx = ex;
        }
        skipCustomData();
        desc.initNonProxy(readDescclresolveExreadClassDesc(false));
        .finish(descHandle);
         = descHandle;
        return desc;
    }

    
Reads in and returns new string. Sets passHandle to new string's assigned handle.
    private String readString(boolean unsharedthrows IOException {
        String str;
        byte tc = .readByte();
        switch (tc) {
            case :
                str = .readUTF();
                break;
            case :
                str = .readLongUTF();
                break;
            default:
                throw new StreamCorruptedException(
                    String.format("invalid type code: %02X"tc));
        }
         = .assign(unshared ?  : str);
        .finish();
        return str;
    }

    
Reads in and returns array object, or null if array class is unresolvable. Sets passHandle to array's assigned handle.
    private Object readArray(boolean unsharedthrows IOException {
        if (.readByte() != ) {
            throw new InternalError();
        }
        ObjectStreamClass desc = readClassDesc(false);
        int len = .readInt();
        Object array = null;
        Class clccl = null;
        if ((cl = desc.forClass()) != null) {
            ccl = cl.getComponentType();
            array = Array.newInstance(ccllen);
        }
        int arrayHandle = .assign(unshared ?  : array);
        ClassNotFoundException resolveEx = desc.getResolveException();
        if (resolveEx != null) {
            .markException(arrayHandleresolveEx);
        }
        if (ccl == null) {
            for (int i = 0; i < leni++) {
                readObject0(false);
            }
        } else if (ccl.isPrimitive()) {
            if (ccl == .) {
                .readInts((int[]) array, 0, len);
            } else if (ccl == .) {
                .readFully((byte[]) array, 0, lentrue);
            } else if (ccl == .) {
                .readLongs((long[]) array, 0, len);
            } else if (ccl == .) {
                .readFloats((float[]) array, 0, len);
            } else if (ccl == .) {
                .readDoubles((double[]) array, 0, len);
            } else if (ccl == .) {
                .readShorts((short[]) array, 0, len);
            } else if (ccl == .) {
                .readChars((char[]) array, 0, len);
            } else if (ccl == .) {
                .readBooleans((boolean[]) array, 0, len);
            } else {
                throw new InternalError();
            }
        } else {
            Object[] oa = (Object[]) array;
            for (int i = 0; i < leni++) {
                oa[i] = readObject0(false);
                .markDependency(arrayHandle);
            }
        }
        .finish(arrayHandle);
         = arrayHandle;
        return array;
    }

    
Reads in and returns enum constant, or null if enum type is unresolvable. Sets passHandle to enum constant's assigned handle.
    private Enum readEnum(boolean unsharedthrows IOException {
        if (.readByte() != ) {
            throw new InternalError();
        }
        ObjectStreamClass desc = readClassDesc(false);
        if (!desc.isEnum()) {
            throw new InvalidClassException("non-enum class: " + desc);
        }
        int enumHandle = .assign(unshared ?  : null);
        ClassNotFoundException resolveEx = desc.getResolveException();
        if (resolveEx != null) {
            .markException(enumHandleresolveEx);
        }
        String name = readString(false);
        Enum en = null;
        Class cl = desc.forClass();
        if (cl != null) {
            try {
                en = Enum.valueOf(clname);
            } catch (IllegalArgumentException ex) {
                throw (IOExceptionnew InvalidObjectException(
                    "enum constant " + name + " does not exist in " +
                    cl).initCause(ex);
            }
            if (!unshared) {
                .setObject(enumHandleen);
            }
        }
        .finish(enumHandle);
         = enumHandle;
        return en;
    }

    
Reads and returns "ordinary" (i.e., not a String, Class, ObjectStreamClass, array, or enum constant) object, or null if object's class is unresolvable (in which case a ClassNotFoundException will be associated with object's handle). Sets passHandle to object's assigned handle.
    private Object readOrdinaryObject(boolean unshared)
        throws IOException
    {
        if (.readByte() != ) {
            throw new InternalError();
        }
        ObjectStreamClass desc = readClassDesc(false);
        desc.checkDeserialize();
        Object obj;
        try {
            obj = desc.isInstantiable() ? desc.newInstance() : null;
        } catch (Exception ex) {
            throw (IOExceptionnew InvalidClassException(
                desc.forClass().getName(),
                "unable to create instance").initCause(ex);
        }
         = .assign(unshared ?  : obj);
        ClassNotFoundException resolveEx = desc.getResolveException();
        if (resolveEx != null) {
            .markException(resolveEx);
        }
        if (desc.isExternalizable()) {
            readExternalData((Externalizableobjdesc);
        } else {
            readSerialData(objdesc);
        }
        .finish();
        if (obj != null &&
            .lookupException() == null &&
            desc.hasReadResolveMethod())
        {
            Object rep = desc.invokeReadResolve(obj);
            if (unshared && rep.getClass().isArray()) {
                rep = cloneArray(rep);
            }
            if (rep != obj) {
                .setObject(obj = rep);
            }
        }
        return obj;
    }

    
If obj is non-null, reads externalizable data by invoking readExternal() method of obj; otherwise, attempts to skip over externalizable data. Expects that passHandle is set to obj's handle before this method is called.
    private void readExternalData(Externalizable objObjectStreamClass desc)
        throws IOException
    {
        CallbackContext oldContext = ;
         = null;
        try {
            boolean blocked = desc.hasBlockExternalData();
            if (blocked) {
                .setBlockDataMode(true);
            }
            if (obj != null) {
                try {
                    obj.readExternal(this);
                } catch (ClassNotFoundException ex) {
                    /*
                     * In most cases, the handle table has already propagated
                     * a CNFException to passHandle at this point; this mark
                     * call is included to address cases where the readExternal
                     * method has cons'ed and thrown a new CNFException of its
                     * own.
                     */
                     .markException(ex);
                }
            }
            if (blocked) {
                skipCustomData();
            }
        } finally {
             = oldContext;
        }
        /*
         * At this point, if the externalizable data was not written in
         * block-data form and either the externalizable class doesn't exist
         * locally (i.e., obj == null) or readExternal() just threw a
         * CNFException, then the stream is probably in an inconsistent state,
         * since some (or all) of the externalizable data may not have been
         * consumed.  Since there's no "correct" action to take in this case,
         * we mimic the behavior of past serialization implementations and
         * blindly hope that the stream is in sync; if it isn't and additional
         * externalizable data remains in the stream, a subsequent read will
         * most likely throw a StreamCorruptedException.
         */
    }

    
Reads (or attempts to skip, if obj is null or is tagged with a ClassNotFoundException) instance data for each serializable class of object in stream, from superclass to subclass. Expects that passHandle is set to obj's handle before this method is called.
    private void readSerialData(Object objObjectStreamClass desc)
        throws IOException
    {
        ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
        for (int i = 0; i < slots.lengthi++) {
            ObjectStreamClass slotDesc = slots[i].;
            if (slots[i].) {
                if (obj != null &&
                    slotDesc.hasReadObjectMethod() &&
                    .lookupException() == null)
                {
                    CallbackContext oldContext = ;
                    try {
                         = new CallbackContext(objslotDesc);
                        .setBlockDataMode(true);
                        slotDesc.invokeReadObject(objthis);
                    } catch (ClassNotFoundException ex) {
                        /*
                         * In most cases, the handle table has already
                         * propagated a CNFException to passHandle at this
                         * point; this mark call is included to address cases
                         * where the custom readObject method has cons'ed and
                         * thrown a new CNFException of its own.
                         */
                        .markException(ex);
                    } finally {
                        .setUsed();
                         = oldContext;
                    }
                    /*
                     * defaultDataEnd may have been set indirectly by custom
                     * readObject() method when calling defaultReadObject() or
                     * readFields(); clear it to restore normal read behavior.
                     */
                     = false;
                } else {
                    defaultReadFields(objslotDesc);
                }
                if (slotDesc.hasWriteObjectData()) {
                    skipCustomData();
                } else {
                    .setBlockDataMode(false);
                }
            } else {
                if (obj != null &&
                    slotDesc.hasReadObjectNoDataMethod() &&
                    .lookupException() == null)
                {
                    slotDesc.invokeReadObjectNoData(obj);
                }
            }
        }
    }

    
Skips over all block data and objects until TC_ENDBLOCKDATA is encountered.
    private void skipCustomData() throws IOException {
        int oldHandle = ;
        for (;;) {
            if (.getBlockDataMode()) {
                .skipBlockData();
                .setBlockDataMode(false);
            }
            switch (.peekByte()) {
                case :
                case :
                    .setBlockDataMode(true);
                    break;
                case :
                    .readByte();
                     = oldHandle;
                    return;
                default:
                    readObject0(false);
                    break;
            }
        }
    }

    
Reads in values of serializable fields declared by given class descriptor. If obj is non-null, sets field values in obj. Expects that passHandle is set to obj's handle before this method is called.
    private void defaultReadFields(Object objObjectStreamClass desc)
        throws IOException
    {
        // REMIND: is isInstance check necessary?
        Class cl = desc.forClass();
        if (cl != null && obj != null && !cl.isInstance(obj)) {
            throw new ClassCastException();
        }
        int primDataSize = desc.getPrimDataSize();
        if ( == null || . < primDataSize) {
             = new byte[primDataSize];
        }
        .readFully(, 0, primDataSizefalse);
        if (obj != null) {
            desc.setPrimFieldValues(obj);
        }
        int objHandle = ;
        ObjectStreamField[] fields = desc.getFields(false);
        Object[] objVals = new Object[desc.getNumObjFields()];
        int numPrimFields = fields.length - objVals.length;
        for (int i = 0; i < objVals.lengthi++) {
            ObjectStreamField f = fields[numPrimFields + i];
            objVals[i] = readObject0(f.isUnshared());
            if (f.getField() != null) {
                .markDependency(objHandle);
            }
        }
        if (obj != null) {
            desc.setObjFieldValues(objobjVals);
        }
         = objHandle;
    }

    
Reads in and returns IOException that caused serialization to abort. All stream state is discarded prior to reading in fatal exception. Sets passHandle to fatal exception's handle.
    private IOException readFatalException() throws IOException {
        if (.readByte() != ) {
            throw new InternalError();
        }
        clear();
        return (IOExceptionreadObject0(false);
    }

    
If recursion depth is 0, clears internal data structures; otherwise, throws a StreamCorruptedException. This method is called when a TC_RESET typecode is encountered.
    private void handleReset() throws StreamCorruptedException {
        if ( > 0) {
            throw new StreamCorruptedException(
                "unexpected reset; recursion depth: " + );
        }
        clear();
    }

    
Converts specified span of bytes into float values.
    // REMIND: remove once hotspot inlines Float.intBitsToFloat
    private static native void bytesToFloats(byte[] srcint srcpos,
                                             float[] dstint dstpos,
                                             int nfloats);

    
Converts specified span of bytes into double values.
    // REMIND: remove once hotspot inlines Double.longBitsToDouble
    private static native void bytesToDoubles(byte[] srcint srcpos,
                                              double[] dstint dstpos,
                                              int ndoubles);

    
Returns the first non-null class loader (not counting class loaders of generated reflection implementation classes) up the execution stack, or null if only code from the null class loader is on the stack. This method is also called via reflection by the following RMI-IIOP class: com.sun.corba.se.internal.util.JDKClassLoader This method should not be removed or its signature changed without corresponding modifications to the above class.
    // REMIND: change name to something more accurate?
    private static native ClassLoader latestUserDefinedLoader();

    
Default GetField implementation.
    private class GetFieldImpl extends GetField {

        
class descriptor describing serializable fields
        private final ObjectStreamClass desc;
        
primitive field values
        private final byte[] primVals;
        
object field values
        private final Object[] objVals;
        
object field value handles
        private final int[] objHandles;

        
Creates GetFieldImpl object for reading fields defined in given class descriptor.
        GetFieldImpl(ObjectStreamClass desc) {
            this. = desc;
             = new byte[desc.getPrimDataSize()];
             = new Object[desc.getNumObjFields()];
             = new int[.];
        }
        public ObjectStreamClass getObjectStreamClass() {
            return ;
        }
        public boolean defaulted(String namethrows IOException {
            return (getFieldOffset(namenull) < 0);
        }
        public boolean get(String nameboolean valthrows IOException {
            int off = getFieldOffset(name.);
            return (off >= 0) ? Bits.getBoolean(off) : val;
        }
        public byte get(String namebyte valthrows IOException {
            int off = getFieldOffset(name.);
            return (off >= 0) ? [off] : val;
        }
        public char get(String namechar valthrows IOException {
            int off = getFieldOffset(name.);
            return (off >= 0) ? Bits.getChar(off) : val;
        }
        public short get(String nameshort valthrows IOException {
            int off = getFieldOffset(name.);
            return (off >= 0) ? Bits.getShort(off) : val;
        }
        public int get(String nameint valthrows IOException {
            int off = getFieldOffset(name.);
            return (off >= 0) ? Bits.getInt(off) : val;
        }
        public float get(String namefloat valthrows IOException {
            int off = getFieldOffset(name.);
            return (off >= 0) ? Bits.getFloat(off) : val;
        }
        public long get(String namelong valthrows IOException {
            int off = getFieldOffset(name.);
            return (off >= 0) ? Bits.getLong(off) : val;
        }
        public double get(String namedouble valthrows IOException {
            int off = getFieldOffset(name.);
            return (off >= 0) ? Bits.getDouble(off) : val;
        }
        public Object get(String nameObject valthrows IOException {
            int off = getFieldOffset(nameObject.class);
            if (off >= 0) {
                int objHandle = [off];
                .markDependency(objHandle);
                return (.lookupException(objHandle) == null) ?
                    [off] : null;
            } else {
                return val;
            }
        }

        
Reads primitive and object field values from stream.
        void readFields() throws IOException {
            .readFully(, 0, .false);
            int oldHandle = ;
            ObjectStreamField[] fields = .getFields(false);
            int numPrimFields = fields.length - .;
            for (int i = 0; i < .i++) {
                [i] =
                    readObject0(fields[numPrimFields + i].isUnshared());
                [i] = ;
            }
             = oldHandle;
        }

        
Returns offset of field with given name and type. A specified type of null matches all types, Object.class matches all non-primitive types, and any other non-null type matches assignable types only. If no matching field is found in the (incoming) class descriptor but a matching field is present in the associated local class descriptor, returns -1. Throws IllegalArgumentException if neither incoming nor local class descriptor contains a match.
        private int getFieldOffset(String nameClass type) {
            ObjectStreamField field = .getField(nametype);
            if (field != null) {
                return field.getOffset();
            } else if (.getLocalDesc().getField(nametype) != null) {
                return -1;
            } else {
                throw new IllegalArgumentException("no such field " + name +
                                                   " with type " + type);
            }
        }
    }

    
Prioritized list of callbacks to be performed once object graph has been completely deserialized.
    private static class ValidationList {
        private static class Callback {
            final ObjectInputValidation obj;
            final int priority;
            Callback next;
            final AccessControlContext acc;
            Callback(ObjectInputValidation objint priorityCallback next,
                AccessControlContext acc)
            {
                this. = obj;
                this. = priority;
                this. = next;
                this. = acc;
            }
        }

        
linked list of callbacks
        private Callback list;

        
Creates new (empty) ValidationList.
        ValidationList() {
        }

        
Registers callback. Throws InvalidObjectException if callback object is null.
        void register(ObjectInputValidation objint priority)
            throws InvalidObjectException
        {
            if (obj == null) {
                throw new InvalidObjectException("null callback");
            }
            Callback prev = nullcur = ;
            while (cur != null && priority < cur.priority) {
                prev = cur;
                cur = cur.next;
            }
            AccessControlContext acc = AccessController.getContext();
            if (prev != null) {
                prev.next = new Callback(objprioritycuracc);
            } else {
                 = new Callback(objpriorityacc);
            }
        }

        
Invokes all registered callbacks and clears the callback list. Callbacks with higher priorities are called first; those with equal priorities may be called in any order. If any of the callbacks throws an InvalidObjectException, the callback process is terminated and the exception propagated upwards.
        void doCallbacks() throws InvalidObjectException {
            try {
                while ( != null) {
                    AccessController.doPrivileged(
                        new PrivilegedExceptionAction()
                    {
                        public Object run() throws InvalidObjectException {
                            ..validateObject();
                            return null;
                        }
                    }, .);
                     = .;
                }
            } catch (PrivilegedActionException ex) {
                 = null;
                throw (InvalidObjectExceptionex.getException();
            }
        }

        
Resets the callback list to its initial (empty) state.
        public void clear() {
             = null;
        }
    }

    
Input stream supporting single-byte peek operations.
    private static class PeekInputStream extends InputStream {

        
underlying stream
        private final InputStream in;
        
peeked byte
        private int peekb = -1;

        
Creates new PeekInputStream on top of given underlying stream.
        PeekInputStream(InputStream in) {
            this. = in;
        }

        
Peeks at next byte value in stream. Similar to read(), except that it does not consume the read value.
        int peek() throws IOException {
            return ( >= 0) ?  : ( = .read());
        }
        public int read() throws IOException {
            if ( >= 0) {
                int v = ;
                 = -1;
                return v;
            } else {
                return .read();
            }
        }
        public int read(byte[] bint offint lenthrows IOException {
            if (len == 0) {
                return 0;
            } else if ( < 0) {
                return .read(bofflen);
            } else {
                b[off++] = (byte;
                len--;
                 = -1;
                int n = .read(bofflen);
                return (n >= 0) ? (n + 1) : 1;
            }
        }
        void readFully(byte[] bint offint lenthrows IOException {
            int n = 0;
            while (n < len) {
                int count = read(boff + nlen - n);
                if (count < 0) {
                    throw new EOFException();
                }
                n += count;
            }
        }
        public long skip(long nthrows IOException {
            if (n <= 0) {
                return 0;
            }
            int skipped = 0;
            if ( >= 0) {
                 = -1;
                skipped++;
                n--;
            }
            return skipped + skip(n);
        }
        public int available() throws IOException {
            return .available() + (( >= 0) ? 1 : 0);
        }
        public void close() throws IOException {
            .close();
        }
    }

    
Input stream with two modes: in default mode, inputs data written in the same format as DataOutputStream; in "block data" mode, inputs data bracketed by block data markers (see object serialization specification for details). Buffering depends on block data mode: when in default mode, no data is buffered in advance; when in block data mode, all data for the current data block is read in at once (and buffered).
    private class BlockDataInputStream
        extends InputStream implements DataInput
    {
        
maximum data block length
        private static final int MAX_BLOCK_SIZE = 1024;
        
maximum data block header length
        private static final int MAX_HEADER_SIZE = 5;
        
(tunable) length of char buffer (for reading strings)
        private static final int CHAR_BUF_SIZE = 256;
        
readBlockHeader() return value indicating header read may block
        private static final int HEADER_BLOCKED = -2;

        
buffer for reading general/block data
        private final byte[] buf = new byte[];
        
buffer for reading block data headers
        private final byte[] hbuf = new byte[];
        
char buffer for fast string reads
        private final char[] cbuf = new char[];

        
block data mode
        private boolean blkmode = false;
        // block data state fields; values meaningful only when blkmode true
        
current offset into buf
        private int pos = 0;
        
end offset of valid data in buf, or -1 if no more block data
        private int end = -1;
        
number of bytes in current block yet to be read from stream
        private int unread = 0;

        
underlying stream (wrapped in peekable filter stream)
        private final PeekInputStream in;
        
loopback stream (for data reads that span data blocks)
        private final DataInputStream din;

        
Creates new BlockDataInputStream on top of given underlying stream. Block data mode is turned off by default.
        BlockDataInputStream(InputStream in) {
            this. = new PeekInputStream(in);
             = new DataInputStream(this);
        }

        
Sets block data mode to the given mode (true == on, false == off) and returns the previous mode value. If the new mode is the same as the old mode, no action is taken. Throws IllegalStateException if block data mode is being switched from on to off while unconsumed block data is still present in the stream.
        boolean setBlockDataMode(boolean newmodethrows IOException {
            if ( == newmode) {
                return ;
            }
            if (newmode) {
                 = 0;
                 = 0;
                 = 0;
            } else if ( < ) {
                throw new IllegalStateException("unread block data");
            }
             = newmode;
            return !;
        }

        
Returns true if the stream is currently in block data mode, false otherwise.
        boolean getBlockDataMode() {
            return ;
        }

        
If in block data mode, skips to the end of the current group of data blocks (but does not unset block data mode). If not in block data mode, throws an IllegalStateException.
        void skipBlockData() throws IOException {
            if (!) {
                throw new IllegalStateException("not in block data mode");
            }
            while ( >= 0) {
                refill();
            }
        }

        
Attempts to read in the next block data header (if any). If canBlock is false and a full header cannot be read without possibly blocking, returns HEADER_BLOCKED, else if the next element in the stream is a block data header, returns the block data length specified by the header, else returns -1.
        private int readBlockHeader(boolean canBlockthrows IOException {
            if () {
                /*
                 * Fix for 4360508: stream is currently at the end of a field
                 * value block written via default serialization; since there
                 * is no terminating TC_ENDBLOCKDATA tag, simulate
                 * end-of-custom-data behavior explicitly.
                 */
                return -1;
            }
            try {
                for (;;) {
                    int avail = canBlock ? . : .available();
                    if (avail == 0) {
                        return ;
                    }
                    int tc = .peek();
                    switch (tc) {
                        case :
                            if (avail < 2) {
                                return ;
                            }
                            .readFully(, 0, 2);
                            return [1] & 0xFF;
                        case :
                            if (avail < 5) {
                                return ;
                            }
                            .readFully(, 0, 5);
                            int len = Bits.getInt(, 1);
                            if (len < 0) {
                                throw new StreamCorruptedException(
                                    "illegal block data header length: " +
                                    len);
                            }
                            return len;
                        /*
                         * TC_RESETs may occur in between data blocks.
                         * Unfortunately, this case must be parsed at a lower
                         * level than other typecodes, since primitive data
                         * reads may span data blocks separated by a TC_RESET.
                         */
                        case :
                            .read();
                            handleReset();
                            break;
                        default:
                            if (tc >= 0 && (tc <  || tc > )) {
                                throw new StreamCorruptedException(
                                    String.format("invalid type code: %02X",
                                    tc));
                            }
                            return -1;
                    }
                }
            } catch (EOFException ex) {
                throw new StreamCorruptedException(
                    "unexpected EOF while reading block data header");
            }
        }

        
Refills internal buffer buf with block data. Any data in buf at the time of the call is considered consumed. Sets the pos, end, and unread fields to reflect the new amount of available block data; if the next element in the stream is not a data block, sets pos and unread to 0 and end to -1.
        private void refill() throws IOException {
            try {
                do {
                     = 0;
                    if ( > 0) {
                        int n =
                            .read(, 0, Math.min());
                        if (n >= 0) {
                             = n;
                             -= n;
                        } else {
                            throw new StreamCorruptedException(
                                "unexpected EOF in middle of data block");
                        }
                    } else {
                        int n = readBlockHeader(true);
                        if (n >= 0) {
                             = 0;
                             = n;
                        } else {
                             = -1;
                             = 0;
                        }
                    }
                } while ( == );
            } catch (IOException ex) {
                 = 0;
                 = -1;
                 = 0;
                throw ex;
            }
        }

        
If in block data mode, returns the number of unconsumed bytes remaining in the current data block. If not in block data mode, throws an IllegalStateException.
        int currentBlockRemaining() {
            if () {
                return ( >= 0) ? ( - ) +  : 0;
            } else {
                throw new IllegalStateException();
            }
        }

        
Peeks at (but does not consume) and returns the next byte value in the stream, or -1 if the end of the stream/block data (if in block data mode) has been reached.
        int peek() throws IOException {
            if () {
                if ( == ) {
                    refill();
                }
                return ( >= 0) ? ([] & 0xFF) : -1;
            } else {
                return .peek();
            }
        }

        
Peeks at (but does not consume) and returns the next byte value in the stream, or throws EOFException if end of stream/block data has been reached.
        byte peekByte() throws IOException {
            int val = peek();
            if (val < 0) {
                throw new EOFException();
            }
            return (byteval;
        }
        /* ----------------- generic input stream methods ------------------ */
        /*
         * The following methods are equivalent to their counterparts in
         * InputStream, except that they interpret data block boundaries and
         * read the requested data from within data blocks when in block data
         * mode.
         */
        public int read() throws IOException {
            if () {
                if ( == ) {
                    refill();
                }
                return ( >= 0) ? ([++] & 0xFF) : -1;
            } else {
                return .read();
            }
        }
        public int read(byte[] bint offint lenthrows IOException {
            return read(bofflenfalse);
        }
        public long skip(long lenthrows IOException {
            long remain = len;
            while (remain > 0) {
                if () {
                    if ( == ) {
                        refill();
                    }
                    if ( < 0) {
                        break;
                    }
                    int nread = (int) Math.min(remain - );
                    remain -= nread;
                     += nread;
                } else {
                    int nread = (int) Math.min(remain);
                    if ((nread = .read(, 0, nread)) < 0) {
                        break;
                    }
                    remain -= nread;
                }
            }
            return len - remain;
        }
        public int available() throws IOException {
            if () {
                if (( == ) && ( == 0)) {
                    int n;
                    while ((n = readBlockHeader(false)) == 0) ;
                    switch (n) {
                        case :
                            break;
                        case -1:
                             = 0;
                             = -1;
                            break;
                        default:
                             = 0;
                             = 0;
                             = n;
                            break;
                    }
                }
                // avoid unnecessary call to in.available() if possible
                int unreadAvail = ( > 0) ?
                    Math.min(.available(), ) : 0;
                return ( >= 0) ? ( - ) + unreadAvail : 0;
            } else {
                return .available();
            }
        }
        public void close() throws IOException {
            if () {
                 = 0;
                 = -1;
                 = 0;
            }
            .close();
        }

        
Attempts to read len bytes into byte array b at offset off. Returns the number of bytes read, or -1 if the end of stream/block data has been reached. If copy is true, reads values into an intermediate buffer before copying them to b (to avoid exposing a reference to b).
        int read(byte[] bint offint lenboolean copythrows IOException {
            if (len == 0) {
                return 0;
            } else if () {
                if ( == ) {
                    refill();
                }
                if ( < 0) {
                    return -1;
                }
                int nread = Math.min(len - );
                System.arraycopy(boffnread);
                 += nread;
                return nread;
            } else if (copy) {
                int nread = .read(, 0, Math.min(len));
                if (nread > 0) {
                    System.arraycopy(, 0, boffnread);
                }
                return nread;
            } else {
                return .read(bofflen);
            }
        }
        /* ----------------- primitive data input methods ------------------ */
        /*
         * The following methods are equivalent to their counterparts in
         * DataInputStream, except that they interpret data block boundaries
         * and read the requested data from within data blocks when in block
         * data mode.
         */
        public void readFully(byte[] bthrows IOException {
            readFully(b, 0, b.lengthfalse);
        }
        public void readFully(byte[] bint offint lenthrows IOException {
            readFully(bofflenfalse);
        }
        public void readFully(byte[] bint offint lenboolean copy)
            throws IOException
        {
            while (len > 0) {
                int n = read(bofflencopy);
                if (n < 0) {
                    throw new EOFException();
                }
                off += n;
                len -= n;
            }
        }
        public int skipBytes(int nthrows IOException {
            return .skipBytes(n);
        }
        public boolean readBoolean() throws IOException {
            int v = read();
            if (v < 0) {
                throw new EOFException();
            }
            return (v != 0);
        }
        public byte readByte() throws IOException {
            int v = read();
            if (v < 0) {
                throw new EOFException();
            }
            return (bytev;
        }
        public int readUnsignedByte() throws IOException {
            int v = read();
            if (v < 0) {
                throw new EOFException();
            }
            return v;
        }
        public char readChar() throws IOException {
            if (!) {
                 = 0;
                .readFully(, 0, 2);
            } else if ( -  < 2) {
                return .readChar();
            }
            char v = Bits.getChar();
             += 2;
            return v;
        }
        public short readShort() throws IOException {
            if (!) {
                 = 0;
                .readFully(, 0, 2);
            } else if ( -  < 2) {
                return .readShort();
            }
            short v = Bits.getShort();
             += 2;
            return v;
        }
        public int readUnsignedShort() throws IOException {
            if (!) {
                 = 0;
                .readFully(, 0, 2);
            } else if ( -  < 2) {
                return .readUnsignedShort();
            }
            int v = Bits.getShort() & 0xFFFF;
             += 2;
            return v;
        }
        public int readInt() throws IOException {
            if (!) {
                 = 0;
                .readFully(, 0, 4);
            } else if ( -  < 4) {
                return .readInt();
            }
            int v = Bits.getInt();
             += 4;
            return v;
        }
        public float readFloat() throws IOException {
            if (!) {
                 = 0;
                .readFully(, 0, 4);
            } else if ( -  < 4) {
                return .readFloat();
            }
            float v = Bits.getFloat();
             += 4;
            return v;
        }
        public long readLong() throws IOException {
            if (!) {
                 = 0;
                .readFully(, 0, 8);
            } else if ( -  < 8) {
                return .readLong();
            }
            long v = Bits.getLong();
             += 8;
            return v;
        }
        public double readDouble() throws IOException {
            if (!) {
                 = 0;
                .readFully(, 0, 8);
            } else if ( -  < 8) {
                return .readDouble();
            }
            double v = Bits.getDouble();
             += 8;
            return v;
        }
        public String readUTF() throws IOException {
            return readUTFBody(readUnsignedShort());
        }
        public String readLine() throws IOException {
            return .readLine();      // deprecated, not worth optimizing
        }
        /* -------------- primitive data array input methods --------------- */
        /*
         * The following methods read in spans of primitive data values.
         * Though equivalent to calling the corresponding primitive read
         * methods repeatedly, these methods are optimized for reading groups
         * of primitive data values more efficiently.
         */
        void readBooleans(boolean[] vint offint lenthrows IOException {
            int stopendoff = off + len;
            while (off < endoff) {
                if (!) {
                    int span = Math.min(endoff - off);
                    .readFully(, 0, span);
                    stop = off + span;
                     = 0;
                } else if ( -  < 1) {
                    v[off++] = .readBoolean();
                    continue;
                } else {
                    stop = Math.min(endoffoff +  - );
                }
                while (off < stop) {
                    v[off++] = Bits.getBoolean(++);
                }
            }
        }
        void readChars(char[] vint offint lenthrows IOException {
            int stopendoff = off + len;
            while (off < endoff) {
                if (!) {
                    int span = Math.min(endoff - off >> 1);
                    .readFully(, 0, span << 1);
                    stop = off + span;
                     = 0;
                } else if ( -  < 2) {
                    v[off++] = .readChar();
                    continue;
                } else {
                    stop = Math.min(endoffoff + (( - ) >> 1));
                }
                while (off < stop) {
                    v[off++] = Bits.getChar();
                     += 2;
                }
            }
        }
        void readShorts(short[] vint offint lenthrows IOException {
            int stopendoff = off + len;
            while (off < endoff) {
                if (!) {
                    int span = Math.min(endoff - off >> 1);
                    .readFully(, 0, span << 1);
                    stop = off + span;
                     = 0;
                } else if ( -  < 2) {
                    v[off++] = .readShort();
                    continue;
                } else {
                    stop = Math.min(endoffoff + (( - ) >> 1));
                }
                while (off < stop) {
                    v[off++] = Bits.getShort();
                     += 2;
                }
            }
        }
        void readInts(int[] vint offint lenthrows IOException {
            int stopendoff = off + len;
            while (off < endoff) {
                if (!) {
                    int span = Math.min(endoff - off >> 2);
                    .readFully(, 0, span << 2);
                    stop = off + span;
                     = 0;
                } else if ( -  < 4) {
                    v[off++] = .readInt();
                    continue;
                } else {
                    stop = Math.min(endoffoff + (( - ) >> 2));
                }
                while (off < stop) {
                    v[off++] = Bits.getInt();
                     += 4;
                }
            }
        }
        void readFloats(float[] vint offint lenthrows IOException {
            int spanendoff = off + len;
            while (off < endoff) {
                if (!) {
                    span = Math.min(endoff - off >> 2);
                    .readFully(, 0, span << 2);
                     = 0;
                } else if ( -  < 4) {
                    v[off++] = .readFloat();
                    continue;
                } else {
                    span = Math.min(endoff - off, (( - ) >> 2));
                }
                bytesToFloats(voffspan);
                off += span;
                 += span << 2;
            }
        }
        void readLongs(long[] vint offint lenthrows IOException {
            int stopendoff = off + len;
            while (off < endoff) {
                if (!) {
                    int span = Math.min(endoff - off >> 3);
                    .readFully(, 0, span << 3);
                    stop = off + span;
                     = 0;
                } else if ( -  < 8) {
                    v[off++] = .readLong();
                    continue;
                } else {
                    stop = Math.min(endoffoff + (( - ) >> 3));
                }
                while (off < stop) {
                    v[off++] = Bits.getLong();
                     += 8;
                }
            }
        }
        void readDoubles(double[] vint offint lenthrows IOException {
            int spanendoff = off + len;
            while (off < endoff) {
                if (!) {
                    span = Math.min(endoff - off >> 3);
                    .readFully(, 0, span << 3);
                     = 0;
                } else if ( -  < 8) {
                    v[off++] = .readDouble();
                    continue;
                } else {
                    span = Math.min(endoff - off, (( - ) >> 3));
                }
                bytesToDoubles(voffspan);
                off += span;
                 += span << 3;
            }
        }

        
Reads in string written in "long" UTF format. "Long" UTF format is identical to standard UTF, except that it uses an 8 byte header (instead of the standard 2 bytes) to convey the UTF encoding length.
        String readLongUTF() throws IOException {
            return readUTFBody(readLong());
        }

        
Reads in the "body" (i.e., the UTF representation minus the 2-byte or 8-byte length header) of a UTF encoding, which occupies the next utflen bytes.
        private String readUTFBody(long utflenthrows IOException {
            StringBuilder sbuf = new StringBuilder();
            if (!) {
                 =  = 0;
            }
            while (utflen > 0) {
                int avail =  - ;
                if (avail >= 3 || (longavail == utflen) {
                    utflen -= readUTFSpan(sbufutflen);
                } else {
                    if () {
                        // near block boundary, read one byte at a time
                        utflen -= readUTFChar(sbufutflen);
                    } else {
                        // shift and refill buffer manually
                        if (avail > 0) {
                            System.arraycopy(, 0, avail);
                        }
                         = 0;
                         = (int) Math.min(utflen);
                        .readFully(avail - avail);
                    }
                }
            }
            return sbuf.toString();
        }

        
Reads span of UTF-encoded characters out of internal buffer (starting at offset pos and ending at or before offset end), consuming no more than utflen bytes. Appends read characters to sbuf. Returns the number of bytes consumed.
        private long readUTFSpan(StringBuilder sbuflong utflen)
            throws IOException
        {
            int cpos = 0;
            int start = ;
            int avail = Math.min( - );
            // stop short of last char unless all of utf bytes in buffer
            int stop =  + ((utflen > avail) ? avail - 2 : (intutflen);
            boolean outOfBounds = false;
            try {
                while ( < stop) {
                    int b1b2b3;
                    b1 = [++] & 0xFF;
                    switch (b1 >> 4) {
                        case 0:
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                        case 7:   // 1 byte format: 0xxxxxxx
                            [cpos++] = (charb1;
                            break;
                        case 12:
                        case 13:  // 2 byte format: 110xxxxx 10xxxxxx
                            b2 = [++];
                            if ((b2 & 0xC0) != 0x80) {
                                throw new UTFDataFormatException();
                            }
                            [cpos++] = (char) (((b1 & 0x1F) << 6) |
                                                   ((b2 & 0x3F) << 0));
                            break;
                        case 14:  // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
                            b3 = [ + 1];
                            b2 = [ + 0];
                             += 2;
                            if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
                                throw new UTFDataFormatException();
                            }
                            [cpos++] = (char) (((b1 & 0x0F) << 12) |
                                                   ((b2 & 0x3F) << 6) |
                                                   ((b3 & 0x3F) << 0));
                            break;
                        default:  // 10xx xxxx, 1111 xxxx
                            throw new UTFDataFormatException();
                    }
                }
            } catch (ArrayIndexOutOfBoundsException ex) {
                outOfBounds = true;
            } finally {
                if (outOfBounds || ( - start) > utflen) {
                    /*
                     * Fix for 4450867: if a malformed utf char causes the
                     * conversion loop to scan past the expected end of the utf
                     * string, only consume the expected number of utf bytes.
                     */
                     = start + (intutflen;
                    throw new UTFDataFormatException();
                }
            }
            sbuf.append(, 0, cpos);
            return  - start;
        }

        
Reads in single UTF-encoded character one byte at a time, appends the character to sbuf, and returns the number of bytes consumed. This method is used when reading in UTF strings written in block data mode to handle UTF-encoded characters which (potentially) straddle block-data boundaries.
        private int readUTFChar(StringBuilder sbuflong utflen)
            throws IOException
        {
            int b1b2b3;
            b1 = readByte() & 0xFF;
            switch (b1 >> 4) {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:     // 1 byte format: 0xxxxxxx
                    sbuf.append((charb1);
                    return 1;
                case 12:
                case 13:    // 2 byte format: 110xxxxx 10xxxxxx
                    if (utflen < 2) {
                        throw new UTFDataFormatException();
                    }
                    b2 = readByte();
                    if ((b2 & 0xC0) != 0x80) {
                        throw new UTFDataFormatException();
                    }
                    sbuf.append((char) (((b1 & 0x1F) << 6) |
                                        ((b2 & 0x3F) << 0)));
                    return 2;
                case 14:    // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
                    if (utflen < 3) {
                        if (utflen == 2) {
                            readByte();         // consume remaining byte
                        }
                        throw new UTFDataFormatException();
                    }
                    b2 = readByte();
                    b3 = readByte();
                    if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) != 0x80) {
                        throw new UTFDataFormatException();
                    }
                    sbuf.append((char) (((b1 & 0x0F) << 12) |
                                        ((b2 & 0x3F) << 6) |
                                        ((b3 & 0x3F) << 0)));
                    return 3;
                default:   // 10xx xxxx, 1111 xxxx
                    throw new UTFDataFormatException();
            }
        }
    }

    
Unsynchronized table which tracks wire handle to object mappings, as well as ClassNotFoundExceptions associated with deserialized objects. This class implements an exception-propagation algorithm for determining which objects should have ClassNotFoundExceptions associated with them, taking into account cycles and discontinuities (e.g., skipped fields) in the object graph.

General use of the table is as follows: during deserialization, a given object is first assigned a handle by calling the assign method. This method leaves the assigned handle in an "open" state, wherein dependencies on the exception status of other handles can be registered by calling the markDependency method, or an exception can be directly associated with the handle by calling markException. When a handle is tagged with an exception, the HandleTable assumes responsibility for propagating the exception to any other objects which depend (transitively) on the exception-tagged object.

Once all exception information/dependencies for the handle have been registered, the handle should be "closed" by calling the finish method on it. The act of finishing a handle allows the exception propagation algorithm to aggressively prune dependency links, lessening the performance/memory impact of exception tracking.

Note that the exception propagation algorithm used depends on handles being assigned/finished in LIFO order; however, for simplicity as well as memory conservation, it does not enforce this constraint.

    // REMIND: add full description of exception propagation algorithm?
    private static class HandleTable {
        /* status codes indicating whether object has associated exception */
        private static final byte STATUS_OK = 1;
        private static final byte STATUS_UNKNOWN = 2;
        private static final byte STATUS_EXCEPTION = 3;

        
array mapping handle -> object status
        byte[] status;
        
array mapping handle -> object/exception (depending on status)
        Object[] entries;
        
array mapping handle -> list of dependent handles (if any)
        HandleList[] deps;
        
lowest unresolved dependency
        int lowDep = -1;
        
number of handles in table
        int size = 0;

        
Creates handle table with the given initial capacity.
        HandleTable(int initialCapacity) {
             = new byte[initialCapacity];
             = new Object[initialCapacity];
             = new HandleList[initialCapacity];
        }

        
Assigns next available handle to given object, and returns assigned handle. Once object has been completely deserialized (and all dependencies on other objects identified), the handle should be "closed" by passing it to finish().
        int assign(Object obj) {
            if ( >= .) {
                grow();
            }
            [] = ;
            [] = obj;
            return ++;
        }

        
Registers a dependency (in exception status) of one handle on another. The dependent handle must be "open" (i.e., assigned, but not finished yet). No action is taken if either dependent or target handle is NULL_HANDLE.
        void markDependency(int dependentint target) {
            if (dependent ==  || target == ) {
                return;
            }
            switch ([dependent]) {
                case :
                    switch ([target]) {
                        case :
                            // ignore dependencies on objs with no exception
                            break;
                        case :
                            // eagerly propagate exception
                            markException(dependent,
                                (ClassNotFoundException[target]);
                            break;
                        case :
                            // add to dependency list of target
                            if ([target] == null) {
                                [target] = new HandleList();
                            }
                            [target].add(dependent);
                            // remember lowest unresolved target seen
                            if ( < 0 ||  > target) {
                                 = target;
                            }
                            break;
                        default:
                            throw new InternalError();
                    }
                    break;
                case :
                    break;
                default:
                    throw new InternalError();
            }
        }

        
Associates a ClassNotFoundException (if one not already associated) with the currently active handle and propagates it to other referencing objects as appropriate. The specified handle must be "open" (i.e., assigned, but not finished yet).
        void markException(int handleClassNotFoundException ex) {
            switch ([handle]) {
                case :
                    [handle] = ;
                    [handle] = ex;
                    // propagate exception to dependents
                    HandleList dlist = [handle];
                    if (dlist != null) {
                        int ndeps = dlist.size();
                        for (int i = 0; i < ndepsi++) {
                            markException(dlist.get(i), ex);
                        }
                        [handle] = null;
                    }
                    break;
                case :
                    break;
                default:
                    throw new InternalError();
            }
        }

        
Marks given handle as finished, meaning that no new dependencies will be marked for handle. Calls to the assign and finish methods must occur in LIFO order.
        void finish(int handle) {
            int end;
            if ( < 0) {
                // no pending unknowns, only resolve current handle
                end = handle + 1;
            } else if ( >= handle) {
                // pending unknowns now clearable, resolve all upward handles
                end = ;
                 = -1;
            } else {
                // unresolved backrefs present, can't resolve anything yet
                return;
            }
            // change STATUS_UNKNOWN -> STATUS_OK in selected span of handles
            for (int i = handlei < endi++) {
                switch ([i]) {
                    case :
                        [i] = ;
                        [i] = null;
                        break;
                    case :
                    case :
                        break;
                    default:
                        throw new InternalError();
                }
            }
        }

        
Assigns a new object to the given handle. The object previously associated with the handle is forgotten. This method has no effect if the given handle already has an exception associated with it. This method may be called at any time after the handle is assigned.
        void setObject(int handleObject obj) {
            switch ([handle]) {
                case :
                case :
                    [handle] = obj;
                    break;
                case :
                    break;
                default:
                    throw new InternalError();
            }
        }

        
Looks up and returns object associated with the given handle. Returns null if the given handle is NULL_HANDLE, or if it has an associated ClassNotFoundException.
        Object lookupObject(int handle) {
            return (handle !=  &&
                    [handle] != ) ?
                [handle] : null;
        }

        
Looks up and returns ClassNotFoundException associated with the given handle. Returns null if the given handle is NULL_HANDLE, or if there is no ClassNotFoundException associated with the handle.
        ClassNotFoundException lookupException(int handle) {
            return (handle !=  &&
                    [handle] == ) ?
                (ClassNotFoundException[handle] : null;
        }

        
Resets table to its initial state.
        void clear() {
            Arrays.fill(, 0, , (byte) 0);
            Arrays.fill(, 0, null);
            Arrays.fill(, 0, null);
             = -1;
             = 0;
        }

        
Returns number of handles registered in table.
        int size() {
            return ;
        }

        
Expands capacity of internal arrays.
        private void grow() {
            int newCapacity = (. << 1) + 1;
            byte[] newStatus = new byte[newCapacity];
            Object[] newEntries = new Object[newCapacity];
            HandleList[] newDeps = new HandleList[newCapacity];
            System.arraycopy(, 0, newStatus, 0, );
            System.arraycopy(, 0, newEntries, 0, );
            System.arraycopy(, 0, newDeps, 0, );
             = newStatus;
             = newEntries;
             = newDeps;
        }

        
Simple growable list of (integer) handles.
        private static class HandleList {
            private int[] list = new int[4];
            private int size = 0;
            public HandleList() {
            }
            public void add(int handle) {
                if ( >= .) {
                    int[] newList = new int[. << 1];
                    System.arraycopy(, 0, newList, 0, .);
                     = newList;
                }
                [++] = handle;
            }
            public int get(int index) {
                if (index >= ) {
                    throw new ArrayIndexOutOfBoundsException();
                }
                return [index];
            }
            public int size() {
                return ;
            }
        }
    }

    
Method for cloning arrays in case of using unsharing reading
    private static Object cloneArray(Object array) {
        if (array instanceof Object[]) {
            return ((Object[]) array).clone();
        } else if (array instanceof boolean[]) {
            return ((boolean[]) array).clone();
        } else if (array instanceof byte[]) {
            return ((byte[]) array).clone();
        } else if (array instanceof char[]) {
            return ((char[]) array).clone();
        } else if (array instanceof double[]) {
            return ((double[]) array).clone();
        } else if (array instanceof float[]) {
            return ((float[]) array).clone();
        } else if (array instanceof int[]) {
            return ((int[]) array).clone();
        } else if (array instanceof long[]) {
            return ((long[]) array).clone();
        } else if (array instanceof double[]) {
            return ((double[]) array).clone();
        } else {
            throw new AssertionError();
        }
    }

    
Context that during upcalls to class-defined readObject methods; holds object currently being deserialized and descriptor for current class. This context keeps a boolean state to indicate that defaultReadObject or readFields has already been invoked with this context or the class's readObject method has returned; if true, the getObj method throws NotActiveException.
    private static class CallbackContext {
        private final Object obj;
        private final ObjectStreamClass desc;
        private final AtomicBoolean used = new AtomicBoolean();
        public CallbackContext(Object objObjectStreamClass desc) {
            this. = obj;
            this. = desc;
        }
        public Object getObj() throws NotActiveException {
            checkAndSetUsed();
            return ;
        }
        public ObjectStreamClass getDesc() {
            return ;
        }
        private void checkAndSetUsed() throws NotActiveException {
            if (!.compareAndSet(falsetrue)) {
                 throw new NotActiveException(
                      "not in readObject invocation or fields already read");
            }
        }
        public void setUsed() {
            .set(true);
        }
    }
New to GrepCode? Check out our FAQ X