objectinputstream.java

来自「gcc3.2.1源代码」· Java 代码 · 共 1,581 行 · 第 1/3 页

JAVA
1,581
字号
/* ObjectInputStream.java -- Class used to read serialized objects   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.This file is part of GNU Classpath.GNU Classpath is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version. GNU Classpath is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Classpath; see the file COPYING.  If not, write to theFree Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307 USA.Linking this library statically or dynamically with other modules ismaking a combined work based on this library.  Thus, the terms andconditions of the GNU General Public License cover the wholecombination.As a special exception, the copyright holders of this library give youpermission to link this library with independent modules to produce anexecutable, regardless of the license terms of these independentmodules, and to copy and distribute the resulting executable underterms of your choice, provided that you also meet, for each linkedindependent module, the terms and conditions of the license of thatmodule.  An independent module is a module which is not derived fromor based on this library.  If you modify this library, you may extendthis exception to your version of the library, but you are notobligated to do so.  If you do not wish to do so, delete thisexception statement from your version. */package java.io;import gnu.classpath.Configuration;import java.lang.reflect.Array;import java.lang.reflect.Modifier;import java.util.Arrays;import java.util.Hashtable;import java.util.Vector;import gnu.java.io.ObjectIdentityWrapper;import gnu.java.lang.reflect.TypeSignature;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.InvocationTargetException;public class ObjectInputStream extends InputStream  implements ObjectInput, ObjectStreamConstants{  /**     Creates a new <code>ObjectInputStream</code> that will do all of     its reading from <code>in</code>.  This method also checks     the stream by reading the header information (stream magic number     and stream version).     @exception IOException Reading stream header from underlying     stream cannot be completed.     @exception StreamCorruptedException An invalid stream magic     number or stream version was read from the stream.     @see readStreamHeader ()  */  public ObjectInputStream (InputStream in)    throws IOException, StreamCorruptedException  {    if (Configuration.DEBUG)      {	String val = System.getProperty("gcj.dumpobjects");	if (dump == false && val != null && !val.equals(""))	  {	    dump = true;	    System.out.println ("Serialization debugging enabled");	  }	else if (dump == true && (val == null || val.equals("")))	  {	    dump = false;	    System.out.println ("Serialization debugging disabled");	  }      }    this.resolveEnabled = false;    this.isDeserializing = false;    this.blockDataPosition = 0;    this.blockDataBytes = 0;    this.blockData = new byte[BUFFER_SIZE];    this.blockDataInput = new DataInputStream (this);    this.realInputStream = new DataInputStream (in);    this.nextOID = baseWireHandle;    this.objectLookupTable = new Hashtable ();    this.validators = new Vector ();    setBlockDataMode (true);    readStreamHeader ();  }  /**     Returns the next deserialized object read from the underlying stream.     This method can be overriden by a class by implementing     <code>private void readObject (ObjectInputStream)</code>.     If an exception is thrown from this method, the stream is left in     an undefined state.     @exception ClassNotFoundException The class that an object being     read in belongs to cannot be found.     @exception IOException Exception from underlying     <code>InputStream</code>.  */  public final Object readObject () throws ClassNotFoundException, IOException  {    if (this.useSubclassMethod)      return readObjectOverride ();    boolean was_deserializing;    Object ret_val;    was_deserializing = this.isDeserializing;    if (! was_deserializing)      setBlockDataMode (false);    this.isDeserializing = true;    byte marker = this.realInputStream.readByte ();    dumpElement ("MARKER: 0x" + Integer.toHexString(marker) + " ");    switch (marker)    {      case TC_BLOCKDATA:      case TC_BLOCKDATALONG:	if (marker == TC_BLOCKDATALONG) 	  dumpElementln ("BLOCKDATALONG");	else	  dumpElementln ("BLOCKDATA");	readNextBlock (marker);	throw new StreamCorruptedException ("Unexpected blockData");      case TC_NULL:	dumpElementln ("NULL");	ret_val = null;	break;      case TC_REFERENCE:      {	dumpElement ("REFERENCE ");	Integer oid = new Integer (this.realInputStream.readInt ());	dumpElementln (Integer.toHexString(oid.intValue()));	ret_val = ((ObjectIdentityWrapper)		   this.objectLookupTable.get (oid)).object;	break;      }      case TC_CLASS:      {	dumpElementln ("CLASS");	ObjectStreamClass osc = (ObjectStreamClass)readObject ();	Class clazz = osc.forClass ();	assignNewHandle (clazz);	ret_val = clazz;	break;      }      case TC_CLASSDESC:      {	dumpElement ("CLASSDESC NAME=");	String name = this.realInputStream.readUTF ();	dumpElement (name + "; UID=");	long uid = this.realInputStream.readLong ();	dumpElement (Long.toHexString(uid) + "; FLAGS=");	byte flags = this.realInputStream.readByte ();	dumpElement (Integer.toHexString(flags) + "; FIELD COUNT=");	short field_count = this.realInputStream.readShort ();	dumpElementln (Short.toString(field_count));	ObjectStreamField[] fields = new ObjectStreamField[field_count];	ObjectStreamClass osc = new ObjectStreamClass (name, uid,						       flags, fields);	assignNewHandle (osc);	for (int i=0; i < field_count; i++)	{	  dumpElement ("  TYPE CODE=");	  char type_code = (char)this.realInputStream.readByte ();	  dumpElement (type_code + "; FIELD NAME=");	  String field_name = this.realInputStream.readUTF ();	  dumpElementln (field_name);	  String class_name;	  if (type_code == 'L' || type_code == '[')	    class_name = (String)readObject ();	  else	    class_name = String.valueOf (type_code);	  fields[i] =	    new ObjectStreamField (field_name,				   TypeSignature.getClassForEncoding				   (class_name));	}	Class cl = resolveClass (osc);	osc.setClass (cl);	setBlockDataMode (false);	if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)	  throw new IOException ("Data annotated to class was not consumed.");	dumpElementln ("ENDBLOCKDATA ");	osc.setSuperclass ((ObjectStreamClass)readObject ());	ret_val = osc;	break;      }      case TC_STRING:      {	dumpElement ("STRING=");	String s = this.realInputStream.readUTF ();	dumpElementln (s);	ret_val = processResolution (s, assignNewHandle (s));	break;      }      case TC_ARRAY:      {	dumpElementln ("ARRAY");	ObjectStreamClass osc = (ObjectStreamClass)readObject ();	Class componentType = osc.forClass ().getComponentType ();	dumpElement ("ARRAY LENGTH=");	int length = this.realInputStream.readInt ();	dumpElementln (length + "; COMPONENT TYPE=" + componentType);	Object array = Array.newInstance (componentType, length);	int handle = assignNewHandle (array);	readArrayElements (array, componentType);	for (int i=0, len=Array.getLength(array); i < len; i++)	  dumpElementln ("  ELEMENT[" + i + "]=" + Array.get(array, i).toString());	ret_val = processResolution (array, handle);	break;      }      case TC_OBJECT:      {	dumpElementln ("OBJECT");	ObjectStreamClass osc = (ObjectStreamClass)readObject ();	Class clazz = osc.forClass ();	if (!Serializable.class.isAssignableFrom (clazz))	  throw new NotSerializableException (clazz + " is not Serializable, and thus cannot be deserialized.");	if (Externalizable.class.isAssignableFrom (clazz))	{	  Externalizable obj = null;	  try	  {	    obj = (Externalizable)clazz.newInstance ();	  }	  catch (InstantiationException e)	  {	    throw new ClassNotFoundException ("Instance of " + clazz					      + " could not be created");	  }	  catch (IllegalAccessException e)	  {	    throw new ClassNotFoundException ("Instance of " + clazz					      + " could not be created because class or zero-argument constructor is not accessible");	  }	  catch (NoSuchMethodError e)	  {	    throw new ClassNotFoundException ("Instance of " + clazz					      + " could not be created because zero-argument constructor is not defined");	  }	  int handle = assignNewHandle (obj);	  boolean read_from_blocks = ((osc.getFlags () & SC_BLOCK_DATA) != 0);	  if (read_from_blocks)	    setBlockDataMode (true);	  obj.readExternal (this);	  if (read_from_blocks)	    setBlockDataMode (false);	  ret_val = processResolution (obj, handle);	  break;	} // end if (Externalizable.class.isAssignableFrom (clazz))	// find the first non-serializable, non-abstract	// class in clazz's inheritance hierarchy	Class first_nonserial = clazz.getSuperclass ();	while (Serializable.class.isAssignableFrom (first_nonserial)	       || Modifier.isAbstract (first_nonserial.getModifiers ()))	  first_nonserial = first_nonserial.getSuperclass ();//	DEBUGln ("Using " + first_nonserial//		 + " as starting point for constructing " + clazz);	Object obj = null;	obj = newObject (clazz, first_nonserial);	if (obj == null)	  throw new ClassNotFoundException ("Instance of " + clazz +					    " could not be created");	int handle = assignNewHandle (obj);	this.currentObject = obj;	ObjectStreamClass[] hierarchy =	  ObjectStreamClass.getObjectStreamClasses (clazz);//	DEBUGln ("Got class hierarchy of depth " + hierarchy.length);	boolean has_read;	for (int i=0; i < hierarchy.length; i++)	{	  this.currentObjectStreamClass = hierarchy[i];	  dumpElementln ("Reading fields of "		   + this.currentObjectStreamClass.getName ());	  has_read = true;	  try	  {	    this.currentObjectStreamClass.forClass ().	      getDeclaredMethod ("readObject", readObjectParams);	  }	  catch (NoSuchMethodException e)	  {	    has_read = false;	  }	  // XXX: should initialize fields in classes in the hierarchy	  // that aren't in the stream	  // should skip over classes in the stream that aren't in the	  // real classes hierarchy	  readFields (obj, this.currentObjectStreamClass.fields,		      has_read, this.currentObjectStreamClass);	  if (has_read)	  {	    dumpElement ("ENDBLOCKDATA? ");	    try	      {		// FIXME: XXX: This try block is to catch EOF which is		// thrown for some objects.  That indicates a bug in the logic.	        if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)		  throw new IOException ("No end of block data seen for class with readObject (ObjectInputStream) method.");	        dumpElementln ("yes");	      }	    catch (EOFException e)	      {	        dumpElementln ("no, got EOFException");	      }	    catch (IOException e)	      {	        dumpElementln ("no, got IOException");	      }	  }	}	this.currentObject = null;	this.currentObjectStreamClass = null;	ret_val = processResolution (obj, handle);	break;      }      case TC_RESET:	dumpElementln ("RESET");	clearHandles ();	ret_val = readObject ();	break;      case TC_EXCEPTION:      {	dumpElement ("EXCEPTION=");	Exception e = (Exception)readObject ();	dumpElementln (e.toString());	clearHandles ();	throw new WriteAbortedException ("Exception thrown during writing of stream", e);      }      default:	throw new IOException ("Unknown marker on stream");    }    this.isDeserializing = was_deserializing;    if (! was_deserializing)    {      setBlockDataMode (true);      if (validators.size () > 0)	invokeValidators ();    }    return ret_val;  }  /**     Reads the current objects non-transient, non-static fields from     the current class from the underlying output stream.     This method is intended to be called from within a object's     <code>private void readObject (ObjectInputStream)</code>     method.     @exception ClassNotFoundException The class that an object being     read in belongs to cannot be found.     @exception NotActiveException This method was called from a     context other than from the current object's and current class's     <code>private void readObject (ObjectInputStream)</code>     method.     @exception IOException Exception from underlying     <code>OutputStream</code>.  */  public void defaultReadObject ()    throws ClassNotFoundException, IOException, NotActiveException  {    if (this.currentObject == null || this.currentObjectStreamClass == null)      throw new NotActiveException ("defaultReadObject called by non-active class and/or object");    if (fieldsAlreadyRead)      throw new NotActiveException ("defaultReadObject called but fields already read from stream (by defaultReadObject or readFields)");    readFields (this.currentObject,		this.currentObjectStreamClass.fields,		false, this.currentObjectStreamClass);    fieldsAlreadyRead = true;  }  /**     Registers a <code>ObjectInputValidation</code> to be carried out     on the object graph currently being deserialized before it is     returned to the original caller of <code>readObject ()</code>.     The order of validation for multiple     <code>ObjectInputValidation</code>s can be controled using     <code>priority</code>.  Validators with higher priorities are     called first.     @see java.io.ObjectInputValidation     @exception InvalidObjectException <code>validator</code> is     <code>null</code>     @exception NotActiveException an attempt was made to add a     validator outside of the <code>readObject</code> method of the     object currently being deserialized  */  public void registerValidation (ObjectInputValidation validator,				  int priority)    throws InvalidObjectException, NotActiveException  {    if (this.currentObject == null || this.currentObjectStreamClass == null)      throw new NotActiveException ("registerValidation called by non-active class and/or object");    if (validator == null)      throw new InvalidObjectException ("attempt to add a null ObjectInputValidation object");    this.validators.addElement (new ValidatorAndPriority (validator,							  priority));  }  /**     Called when a class is being deserialized.  This is a hook to     allow subclasses to read in information written by the     <code>annotateClass (Class)</code> method of an     <code>ObjectOutputStream</code>.     This implementation looks up the active call stack for a     <code>ClassLoader</code>; if a <code>ClassLoader</code> is found,     it is used to load the class associated with <code>osc</code>,     otherwise, the default system <code>ClassLoader</code> is used.     @exception IOException Exception from underlying     <code>OutputStream</code>.     @see java.io.ObjectOutputStream#annotateClass (java.lang.Class)  */  protected Class resolveClass (ObjectStreamClass osc)    throws ClassNotFoundException, IOException  {    SecurityManager sm = System.getSecurityManager ();    // FIXME: currentClassLoader doesn't yet do anything useful. We need    // to call forName() with the classloader of the class which called     // readObject(). See SecurityManager.getClassContext().    ClassLoader cl = currentClassLoader (sm);    return Class.forName (osc.getName (), true, cl);  }  /**     Allows subclasses to resolve objects that are read from the     stream with other objects to be returned in their place.  This     method is called the first time each object is encountered.     This method must be enabled before it will be called in the     serialization process.     @exception IOException Exception from underlying     <code>OutputStream</code>.     @see enableResolveObject (boolean)  */  protected Object resolveObject (Object obj) throws IOException  {    return obj;  }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?