objectinputstream.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 1,655 行 · 第 1/4 页

JAVA
1,655
字号
/* ObjectInputStream.java -- Class used to read serialized objects
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the 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, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.io;

import gnu.java.io.ObjectIdentityWrapper;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Vector;

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 {

		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;

		boolean is_consumed = false;
		boolean old_mode = setBlockDataMode(false);

		this.isDeserializing = true;

		byte marker = this.realInputStream.readByte();
		dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " ");

		try {
			switch (marker) {
				case TC_ENDBLOCKDATA : //wgs
					{
						ret_val = null;
						is_consumed = true;
						break;
					}

				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_PROXYCLASSDESC :
					{
						dumpElementln("PROXYCLASS");
						int n_intf = this.realInputStream.readInt();
						String[] intfs = new String[n_intf];
						for (int i = 0; i < n_intf; i++) {
							intfs[i] = this.realInputStream.readUTF();
							System.out.println(intfs[i]);
						}

						boolean oldmode = setBlockDataMode(true);
						Class cl = resolveProxyClass(intfs);
						setBlockDataMode(oldmode);

						ObjectStreamClass osc = ObjectStreamClass.lookup(cl);
						assignNewHandle(osc);

						if (!is_consumed) {
							byte b = this.realInputStream.readByte();
							if (b != TC_ENDBLOCKDATA)
								throw new IOException(
									"Data annotated to class was not consumed."
										+ b);
						} else
							is_consumed = false;
						ObjectStreamClass superosc =
							(ObjectStreamClass) readObject();
						osc.setSuperclass(superosc);
						ret_val = osc;
						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);

							// There're many cases you can't get java.lang.Class from typename 
							// if your context
							// class loader can't load it, then use typename to construct the field
							fields[i] =
								new ObjectStreamField(field_name, class_name);
							//new ObjectStreamField (field_name, TypeSignature.getClassForEncoding(class_name));
						}

						boolean oldmode = setBlockDataMode(true);
						osc.setClass(resolveClass(osc));
						setBlockDataMode(oldmode);

						if (!is_consumed) {
							byte b = this.realInputStream.readByte();
							if (b != TC_ENDBLOCKDATA)
								throw new IOException(
									"Data annotated to class was not consumed."
										+ b);
						} else
							is_consumed = false;

						osc.setSuperclass((ObjectStreamClass) readObject());
						ret_val = osc;
						break;
					}

				case TC_STRING :
				case TC_LONGSTRING :
					{
						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 componenetType =
							osc.forClass().getComponentType();
						dumpElement("ARRAY LENGTH=");
						int length = this.realInputStream.readInt();
						dumpElementln(
							length + "; COMPONENT TYPE=" + componenetType);
						Object array =
							Array.newInstance(componenetType, length);
						int handle = assignNewHandle(array);
						readArrayElements(array, componenetType);
						for (int i = 0, len = Array.getLength(array);
							i < len;
							i++)
							dumpElementln(
								"  ELEMENT[" + i + "]=" + Array.get(array, i));
						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);

							boolean oldmode = this.readDataFromBlock;
							if (read_from_blocks)
								setBlockDataMode(true);

							obj.readExternal(this);

							if (read_from_blocks)
								setBlockDataMode(oldmode);

							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()

⌨️ 快捷键说明

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