This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FYI: Patch: serialization


Hi list,


I just commited the attached patch to merge some serialization fixes 
from classpath by Jeroen Frijters.


Michael


2004-02-06  Jeroen Frijters  <jeroen@frijters.net>

	* java/io/ObjectInputStream.java: Made all calls
	to dumpElement[ln] conditional on dump flag. (readObject): Changed to
	use cached info from ObjectStreamClass. (readClassDescriptor):
	Cache more information in ObjectStreamClass. (processResolution,
	readFields): Use cached info from ObjectStreamClass.
	(newObject): Throw exception instead of returning null for failure.
	(getField, getMethod, callReadMethod, setBooleanField, setByteField,
	setCharField, setDoubleField, setFloatField, setIntField,
	setLongField, setShortField, setObjectField, readObjectParams):
	Removed. (dumpElement, dumpElementln): Removed dump flag condition
	check.
	* java/io/ObjectStreamField.java (hasReadMethod): Removed.
	(setClass): Added call to cacheMethods() (findMethod): New method.
	(cacheMethods): New method. (ObjectStreamClass): Added call to
	cacheMethods(). (setFields): Cache fields. (getClassUID): Use
	AccessController.doPrivileged to invoke setAccessible.
	(readObjectMethod, readResolveMethod, realClassIsSerializable,
	realClassIsExternalizable, fieldMapping, firstNonSerializableParent):
	New fields.
	* java/io/ObjectStreamField.java (ObjectStreamField): New constructor.
	(ObjectStreamField): Removed FIXME workaround. (getTypeString,
	isPrimitive): Made safe for cases where type == null.
	(setBooleanField, setByteField, setCharField, setShortField,
	setIntField, setLongField, setFloatField, setDoubleField,
	setObjectField): New methods.

Index: java/io/ObjectInputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectInputStream.java,v
retrieving revision 1.25
diff -u -b -B -r1.25 ObjectInputStream.java
--- java/io/ObjectInputStream.java	9 Jan 2004 08:58:58 -0000	1.25
+++ java/io/ObjectInputStream.java	6 Feb 2004 13:26:57 -0000
@@ -138,7 +138,7 @@
     this.isDeserializing = true;
 
     byte marker = this.realInputStream.readByte();
-    dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " ");
+    if(dump) dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " ");
 
     try
       {
@@ -155,25 +155,25 @@
 	  case TC_BLOCKDATALONG:
 	    {
 	      if (marker == TC_BLOCKDATALONG)
-		dumpElementln("BLOCKDATALONG");
+		if(dump) dumpElementln("BLOCKDATALONG");
 	      else
-		dumpElementln("BLOCKDATA");
+		if(dump) dumpElementln("BLOCKDATA");
 	      readNextBlock(marker);
 	      throw new StreamCorruptedException("Unexpected blockData");
 	    }
 
 	  case TC_NULL:
 	    {
-	      dumpElementln("NULL");
+	      if(dump) dumpElementln("NULL");
 	      ret_val = null;
 	      break;
 	    }
 
 	  case TC_REFERENCE:
 	    {
-	      dumpElement("REFERENCE ");
+	      if(dump) dumpElement("REFERENCE ");
 	      Integer oid = new Integer(this.realInputStream.readInt());
-	      dumpElementln(Integer.toHexString(oid.intValue()));
+	      if(dump) dumpElementln(Integer.toHexString(oid.intValue()));
 	      ret_val = ((ObjectIdentityWrapper)
 			 this.objectLookupTable.get(oid)).object;
 	      break;
@@ -181,7 +181,7 @@
 
 	  case TC_CLASS:
 	    {
-	      dumpElementln("CLASS");
+	      if(dump) dumpElementln("CLASS");
 	      ObjectStreamClass osc = (ObjectStreamClass)readObject();
 	      Class clazz = osc.forClass();
 	      assignNewHandle(clazz);
@@ -191,7 +191,7 @@
 
 	  case TC_PROXYCLASSDESC:
 	    {
-	      dumpElementln("PROXYCLASS");
+	      if(dump) dumpElementln("PROXYCLASS");
 	      int n_intf = this.realInputStream.readInt();
 	      String[] intfs = new String[n_intf];
 	      for (int i = 0; i < n_intf; i++)
@@ -242,41 +242,42 @@
 	  case TC_STRING:
 	  case TC_LONGSTRING:
 	    {
-	      dumpElement("STRING=");
+	      if(dump) dumpElement("STRING=");
 	      String s = this.realInputStream.readUTF();
-	      dumpElementln(s);
-	      ret_val = processResolution(s, assignNewHandle(s));
+	      if(dump) dumpElementln(s);
+	      ret_val = processResolution(null, s, assignNewHandle(s));
 	      break;
 	    }
 
 	  case TC_ARRAY:
 	    {
-	      dumpElementln("ARRAY");
+	      if(dump) dumpElementln("ARRAY");
 	      ObjectStreamClass osc = (ObjectStreamClass)readObject();
 	      Class componentType = osc.forClass().getComponentType();
-	      dumpElement("ARRAY LENGTH=");
+	      if(dump) dumpElement("ARRAY LENGTH=");
 	      int length = this.realInputStream.readInt();
-	      dumpElementln (length + "; COMPONENT TYPE=" + componentType);
+	      if(dump) dumpElementln (length + "; COMPONENT TYPE=" + componentType);
 	      Object array = Array.newInstance(componentType, length);
 	      int handle = assignNewHandle(array);
 	      readArrayElements(array, componentType);
+	      if(dump)
 	      for (int i = 0, len = Array.getLength(array); i < len; i++)
 		dumpElementln("  ELEMENT[" + i + "]=" + Array.get(array, i));
-	      ret_val = processResolution(array, handle);
+	      ret_val = processResolution(null, array, handle);
 	      break;
 	    }
 
 	  case TC_OBJECT:
 	    {
-	      dumpElementln("OBJECT");
+	      if(dump) dumpElementln("OBJECT");
 	      ObjectStreamClass osc = (ObjectStreamClass)readObject();
 	      Class clazz = osc.forClass();
 	      
-	      if (!Serializable.class.isAssignableFrom(clazz))
+	      if (!osc.realClassIsSerializable)
 		throw new NotSerializableException
 		  (clazz + " is not Serializable, and thus cannot be deserialized.");
 	      
-	      if (Externalizable.class.isAssignableFrom(clazz))
+	      if (osc.realClassIsExternalizable)
 		{
 		  Externalizable obj = null;
 		  
@@ -315,23 +316,11 @@
 		  if (read_from_blocks)
 		    setBlockDataMode(oldmode);
 		  
-		  ret_val = processResolution(obj, handle);
+		  ret_val = processResolution(osc, obj, handle);
 		  break;
-		} // end if (Externalizable.class.isAssignableFrom (clazz))
+		} // end if (osc.realClassIsExternalizable)
 	      
-	      // 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();
-	      
-	      Object obj = null;
-	      obj = newObject(clazz, first_nonserial);
-	      
-	      if (obj == null)
-		throw new ClassNotFoundException
-		  ("Instance of " + clazz + " could not be created");
+	      Object obj = newObject(clazz, osc.firstNonSerializableParent);
 	      
 	      int handle = assignNewHandle(obj);
 	      this.currentObject = obj;
@@ -342,20 +331,21 @@
 		{
 		  this.currentObjectStreamClass = hierarchy[i];
 		  
-		  dumpElementln("Reading fields of " + this.currentObjectStreamClass.getName ());
+		  if(dump) dumpElementln("Reading fields of " + this.currentObjectStreamClass.getName ());
 
 		  // 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
 		  
-		  if (this.currentObjectStreamClass.hasReadMethod())
+		  Method readObjectMethod = this.currentObjectStreamClass.readObjectMethod;
+		  if (readObjectMethod != null)
 		    {
 		      fieldsAlreadyRead = false;
 		      boolean oldmode = setBlockDataMode(true);
-		      callReadMethod(obj, this.currentObjectStreamClass);
+		      callReadMethod(readObjectMethod, this.currentObjectStreamClass.forClass(), obj);
 		      setBlockDataMode(oldmode);
-		      dumpElement("ENDBLOCKDATA? ");
+		      if(dump) dumpElement("ENDBLOCKDATA? ");
 		      try
 			{
 			  // FIXME: XXX: This try block is to catch EOF which is
@@ -363,15 +353,15 @@
 			  if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
 			    throw new IOException
 			      ("No end of block data seen for class with readObject (ObjectInputStream) method.");
-			  dumpElementln("yes");
+			  if(dump) dumpElementln("yes");
 			}
 		      catch (EOFException e)
 			{
-			  dumpElementln("no, got EOFException");
+			  if(dump) dumpElementln("no, got EOFException");
 			}
 		      catch (IOException e)
 			{
-			  dumpElementln("no, got IOException");
+			  if(dump) dumpElementln("no, got IOException");
 			}
 		    }
 		  else
@@ -382,21 +372,21 @@
 
 	      this.currentObject = null;
 	      this.currentObjectStreamClass = null;
-	      ret_val = processResolution(obj, handle);
+	      ret_val = processResolution(osc, obj, handle);
 	      break;
 	    }
 
 	  case TC_RESET:
-	    dumpElementln("RESET");
+	    if(dump) dumpElementln("RESET");
 	    clearHandles();
 	    ret_val = readObject();
 	    break;
 
 	  case TC_EXCEPTION:
 	    {
-	      dumpElement("EXCEPTION=");
+	      if(dump) dumpElement("EXCEPTION=");
 	      Exception e = (Exception)readObject();
-	      dumpElementln(e.toString());
+	      if(dump) dumpElementln(e.toString());
 	      clearHandles();
 	      throw new WriteAbortedException("Exception thrown during writing of stream", e);
 	    }
@@ -440,27 +430,29 @@
   protected ObjectStreamClass readClassDescriptor()
     throws ClassNotFoundException, IOException
   {
-    dumpElement("CLASSDESC NAME=");
+    if(dump) dumpElement("CLASSDESC NAME=");
     String name = this.realInputStream.readUTF();
-    dumpElement(name + "; UID=");
+    if(dump) dumpElement(name + "; UID=");
     long uid = this.realInputStream.readLong ();
-    dumpElement(Long.toHexString(uid) + "; FLAGS=");
+    if(dump) dumpElement(Long.toHexString(uid) + "; FLAGS=");
     byte flags = this.realInputStream.readByte ();
-    dumpElement(Integer.toHexString(flags) + "; FIELD COUNT=");
+    if(dump) dumpElement(Integer.toHexString(flags) + "; FIELD COUNT=");
     short field_count = this.realInputStream.readShort();
-    dumpElementln(Short.toString(field_count));
+    if(dump) dumpElementln(Short.toString(field_count));
     ObjectStreamField[] fields = new ObjectStreamField[field_count];
     ObjectStreamClass osc = new ObjectStreamClass(name, uid,
 						  flags, fields);
     assignNewHandle(osc);
 	      
+    ClassLoader currentLoader = currentLoader();
+	      
     for (int i = 0; i < field_count; i++)
       {
-	dumpElement("  TYPE CODE=");
+	if(dump) dumpElement("  TYPE CODE=");
 	char type_code = (char)this.realInputStream.readByte();
-	dumpElement(type_code + "; FIELD NAME=");
+	if(dump) dumpElement(type_code + "; FIELD NAME=");
 	String field_name = this.realInputStream.readUTF();
-	dumpElementln(field_name);
+	if(dump) dumpElementln(field_name);
 	String class_name;
 		  
 	// If the type code is an array or an object we must
@@ -473,35 +465,87 @@
 	  class_name = String.valueOf(type_code);
 		  
 	fields[i] =
-	  new ObjectStreamField(field_name, class_name, currentLoader());
+	  new ObjectStreamField(field_name, class_name, currentLoader);
       }
 	      
     /* Now that fields have been read we may resolve the class
      * (and read annotation if needed). */
     Class clazz = resolveClass(osc);
     
-    for (int i = 0; i < field_count; i++)
+    boolean oldmode = setBlockDataMode(true);
+    osc.setClass(clazz, lookupClass(clazz.getSuperclass()));
+    classLookupTable.put(clazz, osc);
+    setBlockDataMode(oldmode);
+
+    // 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();
+
+    osc.firstNonSerializableParent = first_nonserial;
+    osc.realClassIsSerializable = Serializable.class.isAssignableFrom(clazz);
+    osc.realClassIsExternalizable = Externalizable.class.isAssignableFrom(clazz);
+
+    ObjectStreamField[] stream_fields = osc.fields;
+    ObjectStreamField[] real_fields = ObjectStreamClass.lookup(clazz).fields;
+    ObjectStreamField[] fieldmapping = new ObjectStreamField[2 * Math.max(stream_fields.length, real_fields.length)];
+    osc.fieldMapping = fieldmapping;
+
+    int stream_idx = 0;
+    int real_idx = 0;
+    int map_idx = 0;
+
+    while (stream_idx < stream_fields.length
+	   || real_idx < real_fields.length)
+      {
+	ObjectStreamField stream_field = null;
+	ObjectStreamField real_field = null;
+
+	if (stream_idx == stream_fields.length)
+	  {
+	    real_field = real_fields[real_idx++];
+	  }
+	else if (real_idx == real_fields.length)
+	  {
+	    stream_field = stream_fields[stream_idx++];
+	  }
+	else
       {
-	Field f;
+	    int comp_val =
+		real_fields[real_idx].compareTo (stream_fields[stream_idx]);
 	
-	try
+	    if (comp_val < 0)
 	  {
-	    f = clazz.getDeclaredField(fields[i].getName());
-	    if (f != null && !f.getType().equals(fields[i].getType()))
-	      throw new InvalidClassException
-		("invalid field type for " + fields[i].getName() + " in class "
-		 + name + " (requested was \"" + fields[i].getType()
-		 + " and found \"" + f.getType() + "\")"); 
+		real_field = real_fields[real_idx++];
 	  }
-	catch (NoSuchFieldException _)
+	    else if (comp_val > 0)
 	  {
+		stream_field = stream_fields[stream_idx++];
 	  }
+	    else
+	      {
+		stream_field = stream_fields[stream_idx++];
+		real_field = real_fields[real_idx++];
+		if(stream_field.getType() != real_field.getType())
+		    throw new InvalidClassException
+			("invalid field type for " + real_field.getName() +
+			" in class " + name);
+	      }
+	  }
+	if (stream_field != null)
+	  {
+	    if (stream_field.getOffset() < 0)
+		stream_field = null;
+	    else if (!stream_field.isToSet())
+		real_field = null;
+	  }
+	if (real_field != null && !real_field.isToSet())
+	    real_field = null;
+	fieldmapping[map_idx++] = stream_field;
+	fieldmapping[map_idx++] = real_field;
       }
-
-    boolean oldmode = setBlockDataMode(true);
-    osc.setClass(clazz, lookupClass(clazz.getSuperclass()));
-    classLookupTable.put(clazz, osc);
-    setBlockDataMode(oldmode);
 
     return osc;
   }
@@ -763,11 +807,11 @@
   protected void readStreamHeader()
     throws IOException, StreamCorruptedException
   {
-    dumpElement("STREAM MAGIC ");
+    if(dump) dumpElement("STREAM MAGIC ");
     if (this.realInputStream.readShort() != STREAM_MAGIC)
       throw new StreamCorruptedException("Invalid stream magic number");
 
-    dumpElementln("STREAM VERSION ");
+    if(dump) dumpElementln("STREAM VERSION ");
     if (this.realInputStream.readShort() != STREAM_VERSION)
       throw new StreamCorruptedException("Invalid stream version number");
   }
@@ -1045,7 +1089,7 @@
    * deserializing class (if present). It cannot (and should not)be called
    * outside of it. Its goal is to read all fields in the real input stream
    * and keep them accessible through the {@link #GetField} class. Calling
-   * this method will not alterate the deserializing object.
+   * this method will not alter the deserializing object.
    *
    * @return A valid freshly created 'GetField' instance to get access to
    * the deserialized stream.
@@ -1375,20 +1419,18 @@
     return this.nextOID++;
   }
 
-  private Object processResolution(Object obj, int handle)
+  private Object processResolution(ObjectStreamClass osc, Object obj, int handle)
     throws IOException
   {
-    if (obj instanceof Serializable)
+    if (osc != null && obj instanceof Serializable)
       {
-        Method m = null; 
 	try
 	  {
-	    Class classArgs[] = {};
-	    m = getMethod(obj.getClass(), "readResolve", classArgs);
+	    Method m = osc.readResolveMethod; 
+	    if(m != null)
+	    {
 	    obj = m.invoke(obj, new Object[] {});	
 	  }
-	catch (NoSuchMethodException ignore)
-	  {
 	  }
 	catch (IllegalAccessException ignore)
 	  {
@@ -1422,15 +1464,15 @@
   {
     if (marker == TC_BLOCKDATA)
       {
-	dumpElement("BLOCK DATA SIZE=");
+	if(dump) dumpElement("BLOCK DATA SIZE=");
 	this.blockDataBytes = this.realInputStream.readUnsignedByte();
-	dumpElementln (Integer.toString(this.blockDataBytes));
+	if(dump) dumpElementln (Integer.toString(this.blockDataBytes));
       }
     else if (marker == TC_BLOCKDATALONG)
       {
-	dumpElement("BLOCK DATA LONG SIZE=");
+	if(dump) dumpElement("BLOCK DATA LONG SIZE=");
 	this.blockDataBytes = this.realInputStream.readInt();
-	dumpElementln (Integer.toString(this.blockDataBytes));
+	if(dump) dumpElementln (Integer.toString(this.blockDataBytes));
       }
     else
       {
@@ -1517,158 +1559,123 @@
   private void readFields (Object obj, ObjectStreamClass stream_osc)
     throws ClassNotFoundException, IOException
   {
-    ObjectStreamField[] stream_fields = stream_osc.fields;
-    ObjectStreamField[] real_fields =
-      lookupClass(stream_osc.forClass()).fields;
-
-    boolean default_initialize, set_value;
-    String field_name = null;
-    Class type = null;
-    ObjectStreamField stream_field = null;
-    ObjectStreamField real_field = null;
-    int stream_idx = 0;
-    int real_idx = 0;
+    ObjectStreamField[] fields = stream_osc.fieldMapping;
 
-    while (stream_idx < stream_fields.length
-	   && real_idx < real_fields.length)
+    for (int i = 0; i < fields.length; i += 2)
       {
-	default_initialize = false;
-	set_value = true;
-
-	if (stream_idx == stream_fields.length)
-	  default_initialize = true;
-	else
+	ObjectStreamField stream_field = fields[i];
+	ObjectStreamField real_field = fields[i + 1];
+	if(stream_field != null || real_field != null)
+	  {
+	    boolean read_value = stream_field != null;
+	    boolean set_value = real_field != null;
+	    String field_name;
+	    char type;
+	    if (stream_field != null)
 	  {
-	    stream_field = stream_fields[stream_idx];
-	    type = stream_field.getType();
+		field_name = stream_field.getName();
+		type = stream_field.getTypeCode();
 	  }
-
-	if (real_idx == real_fields.length)
-	  set_value = false;
 	else
 	  {
-	    real_field = real_fields[real_idx];
-	    type = real_field.getType();
 	    field_name = real_field.getName();
+		type = real_field.getTypeCode();
 	  }
 
-	if (set_value && !default_initialize)
-	  {
-	    int comp_val =
-	      real_field.compareTo (stream_field);
-
-	    if (comp_val < 0)
-	      {
-		default_initialize = true;
-		real_idx++;
-	      }
-	    else if (comp_val > 0)
+	    switch(type)
 	      {
-		set_value = false;
-		stream_idx++;
-	      }
-	    else
-	      {
-		real_idx++;
-		stream_idx++;
-	      }
-	  }
-
-	if (stream_field.getOffset() < 0)
-	  {
-	    default_initialize = true;
-	    set_value = false;
-	  }
-	
-	if (!stream_field.isToSet()) 
-	  set_value = false;
-
-	try
-	  {
-	    if (type == Boolean.TYPE)
+		case 'Z':
 	      {
 		boolean value =
-		  default_initialize ? false : this.realInputStream.readBoolean();
-		if (!default_initialize && set_value)
+			read_value ? this.realInputStream.readBoolean() : false;
+		    if (dump && read_value && set_value)
 		  dumpElementln("  " + field_name + ": " + value);
 		if (set_value)
-		  setBooleanField(obj, stream_osc.forClass(), field_name, value);
+			real_field.setBooleanField(obj, value);
+		    break;
 	      }
-	    else if (type == Byte.TYPE)
+		case 'B':
 	      {
 		byte value =
-		  default_initialize ? 0 : this.realInputStream.readByte();
-		if (!default_initialize && set_value)
+			read_value ? this.realInputStream.readByte() : 0;
+		    if (dump && read_value && set_value)
 		  dumpElementln("  " + field_name + ": " + value);
 		if (set_value)
-		  setByteField(obj, stream_osc.forClass(), field_name, value);
+			real_field.setByteField(obj, value);
+		    break;
 	      }
-	    else if (type == Character.TYPE)
+		case 'C':
 	      {
 		char value =
-		  default_initialize ? (char)0 : this.realInputStream.readChar();
-		if (!default_initialize && set_value)
+			read_value ? this.realInputStream.readChar(): 0;
+		    if (dump && read_value && set_value)
 		  dumpElementln("  " + field_name + ": " + value);
 		if (set_value)
-		  setCharField(obj, stream_osc.forClass(), field_name, value);
+			real_field.setCharField(obj, value);
+		    break;
 	      }
-	    else if (type == Double.TYPE)
+		case 'D':
 	      {
 		double value =
-		  default_initialize ? 0 : this.realInputStream.readDouble();
-		if (!default_initialize && set_value)
+			read_value ? this.realInputStream.readDouble() : 0;
+		    if (dump && read_value && set_value)
 		  dumpElementln("  " + field_name + ": " + value);
 		if (set_value)
-		  setDoubleField(obj, stream_osc.forClass(), field_name, value);
+			real_field.setDoubleField(obj, value);
+		    break;
 	      }
-	    else if (type == Float.TYPE)
+		case 'F':
 	      {
 		float value =
-		  default_initialize ? 0 : this.realInputStream.readFloat();
-		if (!default_initialize && set_value)
+			read_value ? this.realInputStream.readFloat() : 0;
+		    if (dump && read_value && set_value)
 		  dumpElementln("  " + field_name + ": " + value);
 		if (set_value)
-		  setFloatField(obj, stream_osc.forClass(), field_name, value);
+			real_field.setFloatField(obj, value);
+		    break;
 	      }
-	    else if (type == Integer.TYPE)
+		case 'I':
 	      {
 		int value =
-		  default_initialize ? 0 : this.realInputStream.readInt();
-		if (!default_initialize && set_value)
+			read_value ? this.realInputStream.readInt() : 0;
+		    if (dump && read_value && set_value)
 		  dumpElementln("  " + field_name + ": " + value);
 		if (set_value)
-		  setIntField(obj, stream_osc.forClass(), field_name, value);
+			real_field.setIntField(obj, value);
+		    break;
 	      }
-	    else if (type == Long.TYPE)
+		case 'J':
 	      {
 		long value =
-		  default_initialize ? 0 : this.realInputStream.readLong();
-		if (!default_initialize && set_value)
+			read_value ? this.realInputStream.readLong() : 0;
+		    if (dump && read_value && set_value)
 		  dumpElementln("  " + field_name + ": " + value);
 		if (set_value)
-		  setLongField(obj, stream_osc.forClass(), field_name, value);
+			real_field.setLongField(obj, value);
+		    break;
 	      }
-	    else if (type == Short.TYPE)
+		case 'S':
 	      {
 		short value =
-		  default_initialize ? (short)0 : this.realInputStream.readShort();
-		if (!default_initialize && set_value)
+			read_value ? this.realInputStream.readShort() : 0;
+		    if (dump && read_value && set_value)
 		  dumpElementln("  " + field_name + ": " + value);
 		if (set_value)
-		  setShortField(obj, stream_osc.forClass(), field_name, value);
+			real_field.setShortField(obj, value);
+		    break;
 	      }
-	    else
+		case 'L':
+		case '[':
 	      {
 		Object value =
-		  default_initialize ? null : readObject();
+			read_value ? readObject() : null;
 		if (set_value)
-		  setObjectField(obj, stream_osc.forClass(), field_name,
-				  real_field.getTypeString(), value);
+			real_field.setObjectField(obj, value);
+		    break;
 	      }
+		default:
+		    throw new InternalError("Invalid type code: " + type);
 	  }
-	catch (NoSuchFieldError e)
-	  {
-	    dumpElementln("XXXX " + field_name + " does not exist.");
 	  }
       }
   }
@@ -1689,6 +1696,7 @@
   // returns a new instance of REAL_CLASS that has been constructed
   // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS)
   private Object newObject (Class real_class, Class constructor_class)
+    throws ClassNotFoundException
   {
     try
       {
@@ -1698,7 +1706,8 @@
       }
     catch (InstantiationException e)
       {
-	return null;
+        throw new ClassNotFoundException
+		("Instance of " + real_class + " could not be created");
       }
   }
 
@@ -1728,77 +1737,13 @@
    * @param sm SecurityManager instance which should be called.
    * @return The current class loader in the calling stack.
    */
-  private static ClassLoader currentClassLoader (SecurityManager sm)
-  {
-    // FIXME: This is too simple.
-    return ClassLoader.getSystemClassLoader ();
-  }
-
-  /**
-   * This method tries to access a precise field called in the
-   * specified class. Before accessing the field, it tries to
-   * gain control on this field. If the field is either declared as 
-   * not persistent or transient then it returns null
-   * immediately.
-   *
-   * @param klass Class to get the field from.
-   * @param name Name of the field to access.
-   * @return Field instance representing the requested field.
-   * @throws NoSuchFieldException if the field does not exist.
-   */
-  private Field getField(Class klass, String name)
-    throws java.lang.NoSuchFieldException
-  {
-    final Field f = klass.getDeclaredField(name);
-    ObjectStreamField sf = lookupClass(klass).getField(name);
-    
-    AccessController.doPrivileged(new PrivilegedAction()
-      {
-	public Object run()
-	{
-	  f.setAccessible(true);
-	  return null;
-	}
-      });
-
-    /* We do not want to modify transient fields. They should
-     * be left to 0.
-     * N.B.: Not valid if the field is in serialPersistentFields. 
-     */
-    if (Modifier.isTransient(f.getModifiers()) && !sf.isPersistent())
-      return null;
-   
-    return f;
-  }
-
-  private static Method getMethod (Class klass, String name, Class args[])
-    throws java.lang.NoSuchMethodException
-  {
-    final Method m = klass.getDeclaredMethod(name, args);
-    AccessController.doPrivileged(new PrivilegedAction()
-      {
-	public Object run()
-	{
-	  m.setAccessible(true);
-	  return null;
-	}
-      });
-    return m;
-  }
+  private static native ClassLoader currentClassLoader (SecurityManager sm);
 
-  private void callReadMethod (Object obj, ObjectStreamClass osc) throws IOException
+  private void callReadMethod (Method readObject, Class klass, Object obj) throws IOException
   {
-    Class klass = osc.forClass();
     try
       {
-	Class classArgs[] = {ObjectInputStream.class};
-	Method m = getMethod (klass, "readObject", classArgs);
-	Object args[] = {this};
-	m.invoke(obj, args);
-      }
-    catch (NoSuchMethodException nsme)
-      {
-	// Nothing.
+	readObject.invoke(obj, new Object[] { this });
       }
     catch (InvocationTargetException x)
       {
@@ -1827,265 +1772,7 @@
 
   private native void callConstructor (Class clazz, Object obj);
 
-  /**
-   * This method writes a "boolean" value <code>val</code> in the specified field
-   * of the instance <code>obj</code> of the type <code>klass</code>.
-   *
-   * @param obj Instance to setup.
-   * @param klass Class type of the specified instance.
-   * @param field_name Name of the field in the specified class type.
-   * @param val The boolean value to write into the field.
-   * @throws InvalidClassException if the specified field has not the required type.
-   * @throws IOException if there is no field of that name in the specified class.
-   */
-  private void setBooleanField(Object obj, Class klass, String field_name,
-				boolean val) throws IOException, InvalidClassException
-  {
-    try
-      {
-	Field f = getField(klass, field_name);
-	f.setBoolean(obj, val);
-      }
-    catch (IllegalArgumentException _)
-      {
-	throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
-      }
-    catch (Exception _)
-      {
-      }    
-  }
-
-  /**
-   * This method writes a "byte" value <code>val</code> in the specified field
-   * of the instance <code>obj</code> of the type <code>klass</code>.
-   *
-   * @param obj Instance to setup.
-   * @param klass Class type of the specified instance.
-   * @param field_name Name of the field in the specified class type.
-   * @param val The byte value to write into the field.
-   * @throws InvalidClassException if the specified field has not the required type.
-   * @throws IOException if there is no field of that name in the specified class.
-   */
-  private void setByteField(Object obj, Class klass, String field_name,
-			     byte val) throws IOException, InvalidClassException
-  {
-    try
-      {
-	Field f = getField(klass, field_name);
-	f.setByte(obj, val);
-      }
-    catch (IllegalArgumentException _)
-      {
-	throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
-      }
-    catch (Exception _)
-      {
-      }    
-  }
-
-  /**
-   * This method writes a "character" value <code>val</code> in the specified field
-   * of the instance <code>obj</code> of the type <code>klass</code>.
-   *
-   * @param obj Instance to setup.
-   * @param klass Class type of the specified instance.
-   * @param field_name Name of the field in the specified class type.
-   * @param val The character value to write into the field.
-   * @throws InvalidClassException if the specified field has not the required type.
-   * @throws IOException if there is no field of that name in the specified class.
-   */
-  private void setCharField(Object obj, Class klass, String field_name,
-			     char val) throws IOException, InvalidClassException
-  {
-    try
-      {
-	Field f = getField(klass, field_name);
-	f.setChar(obj, val);
-      }
-    catch (IllegalArgumentException _)
-      {
-	throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
-      }
-    catch (Exception _)
-      {
-      }    
-  }
-
-  /**
-   * This method writes a "double" value <code>val</code> in the specified field
-   * of the instance <code>obj</code> of the type <code>klass</code>.
-   *
-   * @param obj Instance to setup.
-   * @param klass Class type of the specified instance.
-   * @param field_name Name of the field in the specified class type.
-   * @param val The double value to write into the field.
-   * @throws InvalidClassException if the specified field has not the required type.
-   * @throws IOException if there is no field of that name in the specified class.
-   */
-  private void setDoubleField(Object obj, Class klass, String field_name,
-			       double val) throws IOException, InvalidClassException
-  {
-    try
-      {
-	Field f = getField(klass, field_name);
-	f.setDouble(obj, val);
-      }
-    catch (IllegalArgumentException _)
-      {
-	throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
-      }
-    catch (Exception _)
-      {
-      }    
-  }
-
-  /**
-   * This method writes a "float" value <code>val</code> in the specified field
-   * of the instance <code>obj</code> of the type <code>klass</code>.
-   *
-   * @param obj Instance to setup.
-   * @param klass Class type of the specified instance.
-   * @param field_name Name of the field in the specified class type.
-   * @param val The float value to write into the field.
-   * @throws InvalidClassException if the specified field has not the required type.
-   * @throws IOException if there is no field of that name in the specified class.
-   */
-  private void setFloatField(Object obj, Class klass, String field_name,
-			      float val) throws IOException, InvalidClassException
-  {
-    try
-      {
-	Field f = getField(klass, field_name);
-	f.setFloat(obj, val);
-      }
-    catch (IllegalArgumentException _)
-      {
-	throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
-      }
-    catch (Exception _)
-      {
-      }    
-  }
-
-  /**
-   * This method writes an "integer" value <code>val</code> in the specified field
-   * of the instance <code>obj</code> of the type <code>klass</code>.
-   *
-   * @param obj Instance to setup.
-   * @param klass Class type of the specified instance.
-   * @param field_name Name of the field in the specified class type.
-   * @param val The integer value to write into the field.
-   * @throws InvalidClassException if the specified field has not the required type.
-   * @throws IOException if there is no field of that name in the specified class.
-   */
-  private void setIntField(Object obj, Class klass, String field_name,
-			    int val) throws IOException, InvalidClassException
-  {
-    try
-      {
-	Field f = getField(klass, field_name);
-	f.setInt(obj, val);
-      }
-    catch (IllegalArgumentException _)
-      {
-	throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
-      }
-    catch (Exception _)
-      {
-      }    
-  }
-
-  /**
-   * This method writes the long value <code>val</code> in the specified field
-   * of the instance <code>obj</code> of the type <code>klass</code>.
-   *
-   * @param obj Instance to setup.
-   * @param klass Class type of the specified instance.
-   * @param field_name Name of the field in the specified class type.
-   * @param val The long value to write into the field.
-   * @throws InvalidClassException if the specified field has not the required type.
-   * @throws IOException if there is no field of that name in the specified class.
-   */
-  private void setLongField(Object obj, Class klass, String field_name,
-			     long val) throws IOException, InvalidClassException
-  {
-    try
-      {
-	Field f = getField(klass, field_name);
-	f.setLong(obj, val);
-      }
-    catch (IllegalArgumentException _)
-      {
-	throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
-      }
-    catch (Exception _)
-      {
-      }    
-  }
-
-  /**
-   * This method writes a "short" value <code>val</code> in the specified field
-   * of the instance <code>obj</code> of the type <code>klass</code>.
-   *
-   * @param obj Instance to setup.
-   * @param klass Class type of the specified instance.
-   * @param field_name Name of the field in the specified class type.
-   * @param val The short value to write into the field.
-   * @throws InvalidClassException if the specified field has not the required type.
-   * @throws IOException if there is no field of that name in the specified class.
-   */
-  private void setShortField(Object obj, Class klass, String field_name,
-			      short val) throws IOException, InvalidClassException
-  {
-    try
-      {
-	Field f = getField(klass, field_name);
-	f.setShort(obj, val);
-      }
-    catch (IllegalArgumentException _)
-      {
-	throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
-      }
-    catch (Exception _)
-      {
-      }    
-  }
-
-  /**
-   * This method writes an "object" value <code>val</code> in the specified field
-   * of the instance <code>obj</code> of the type <code>klass</code>.
-   *
-   * @param obj Instance to setup.
-   * @param klass Class type of the specified instance.
-   * @param field_name Name of the field in the specified class type.
-   * @param val The "object" value to write into the field.
-   * @throws InvalidClassException if the specified field has not the required type.
-   * @throws IOException if there is no field of that name in the specified class.
-   */
-  private void setObjectField(Object obj, Class klass, String field_name,
-			       String type_code, Object val) throws IOException, InvalidClassException
-  {
-    try
-      {
- 	Field f = getField(klass, field_name);
-	ObjectStreamField of = new ObjectStreamField(field_name, f.getType());
-	
-	if (of.getTypeString() == null ||
-	    !of.getTypeString().equals(type_code))
-          throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name);
- 	f.set(obj, val);
-      }
-    catch (InvalidClassException e)
-      {
-	throw e;
-      }
-    catch (Exception _)
-      {
-      }
-  }
-
   private static final int BUFFER_SIZE = 1024;
-  private static final Class[] readObjectParams = { ObjectInputStream.class };
 
   private DataInputStream realInputStream;
   private DataInputStream dataInputStream;
@@ -2106,17 +1793,15 @@
   private Hashtable classLookupTable;
   private GetField prereadFields;
 
-  private static boolean dump;
+  private static boolean dump = false && Configuration.DEBUG;
 
   private void dumpElement (String msg)
   {
-    if (Configuration.DEBUG && dump)  
       System.out.print(msg);
   }
   
   private void dumpElementln (String msg)
   {
-    if (Configuration.DEBUG && dump)
       System.out.println(msg);
   }
 
Index: java/io/ObjectStreamClass.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectStreamClass.java,v
retrieving revision 1.18
diff -u -b -B -r1.18 ObjectStreamClass.java
--- java/io/ObjectStreamClass.java	30 Dec 2003 15:51:15 -0000	1.18
+++ java/io/ObjectStreamClass.java	6 Feb 2004 13:26:59 -0000
@@ -45,9 +45,11 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
+import java.security.AccessController;
 import java.security.DigestOutputStream;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedAction;
 import java.security.Security;
 import java.util.Arrays;
 import java.util.Comparator;
@@ -192,29 +194,6 @@
     return (flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0;
   }
 
-
-  // Returns true iff the class that this ObjectStreamClass represents
-  // has the following method:
-  //
-  // private void readObject (ObjectOutputStream)
-  //
-  // This method is used by the class to override default
-  // serialization behavior.
-  boolean hasReadMethod()
-  {
-    try
-      {
-	Class[] readObjectParams = { ObjectInputStream.class };
-	forClass().getDeclaredMethod("readObject", readObjectParams);
-	return true;
-      }
-    catch (NoSuchMethodException e)
-      {
-	return false;
-      }
-  }
-
-
   // Returns true iff the class that this ObjectStreamClass represents
   // implements Serializable but does *not* implement Externalizable.
   boolean isSerializable()
@@ -306,6 +285,8 @@
   {
     this.clazz = cl;
 
+    cacheMethods();
+
     long class_uid = getClassUID(cl);
     if (uid == 0)
       uid = class_uid;
@@ -452,6 +433,50 @@
       fields[i].setOffset(objectFieldCount++);
   }
 
+  private Method findMethod(Method[] methods, String name, Class[] params,
+			    Class returnType)
+  {
+outer:
+    for(int i = 0; i < methods.length; i++)
+    {
+	if(methods[i].getName().equals(name) &&
+	   methods[i].getReturnType() == returnType)
+	{
+	    Class[] mp = methods[i].getParameterTypes();
+	    if(mp.length == params.length)
+	    {
+		for(int j = 0; j < mp.length; j++)
+		{
+		    if(mp[j] != params[j])
+		    {
+			continue outer;
+		    }
+		}
+		final Method m = methods[i];
+		AccessController.doPrivileged(new PrivilegedAction()
+		{
+		    public Object run()
+		    {
+			m.setAccessible(true);
+			return null;
+		    }
+		});
+		return m;
+	    }
+	}
+    }
+    return null;
+  }
+
+  private void cacheMethods()
+  {
+    Method[] methods = forClass().getDeclaredMethods();
+    readObjectMethod = findMethod(methods, "readObject",
+				  new Class[] { ObjectInputStream.class },
+				  Void.TYPE);
+    readResolveMethod = findMethod(methods, "readResolve",
+				   new Class[0], Object.class);
+  }
 
   private ObjectStreamClass(Class cl)
   {
@@ -460,6 +485,7 @@
     isProxyClass = Proxy.isProxyClass(cl);
 
     clazz = cl;
+    cacheMethods();
     name = cl.getName();
     setFlags(cl);
     setFields(cl);
@@ -508,9 +534,16 @@
 
     try
       {
-	Field serialPersistentFields =
+	final Field serialPersistentFields =
 	  cl.getDeclaredField("serialPersistentFields");
+	AccessController.doPrivileged(new PrivilegedAction()
+	{
+	    public Object run()
+	    {
 	serialPersistentFields.setAccessible(true);
+		return null;
+	    }
+	});
 	int modifiers = serialPersistentFields.getModifiers();
 
 	if (Modifier.isStatic(modifiers)
@@ -553,12 +586,28 @@
     for (int from = 0, to = 0; from < all_fields.length; from++)
       if (all_fields[from] != null)
 	{
-	  Field f = all_fields[from];
-	  fields[to] = new ObjectStreamField(f.getName(), f.getType());
+	  final Field f = all_fields[from];
+	  AccessController.doPrivileged(new PrivilegedAction()
+	  {
+	      public Object run()
+	      {
+		  f.setAccessible(true);
+		  return null;
+	      }
+	  });
+	  fields[to] = new ObjectStreamField(all_fields[from]);
 	  to++;
 	}
 
     Arrays.sort(fields);
+    // Make sure we don't have any duplicate field names
+    // (Sun JDK 1.4.1. throws an Internal Error as well)
+    for (int i = 1; i < fields.length; i++)
+      {
+	if(fields[i - 1].getName().equals(fields[i].getName()))
+	    throw new InternalError("Duplicate field " + 
+			fields[i].getName() + " in class " + cl.getName());
+      }
     calculateOffsets();
   }
 
@@ -571,8 +620,15 @@
 	// Use getDeclaredField rather than getField, since serialVersionUID
 	// may not be public AND we only want the serialVersionUID of this
 	// class, not a superclass or interface.
-	Field suid = cl.getDeclaredField("serialVersionUID");
+	final Field suid = cl.getDeclaredField("serialVersionUID");
+	AccessController.doPrivileged(new PrivilegedAction()
+	{
+	    public Object run()
+	    {
 	suid.setAccessible(true);
+		return null;
+	    }
+	});
 	int modifiers = suid.getModifiers();
 
 	if (Modifier.isStatic(modifiers)
@@ -768,6 +824,13 @@
   // these are accessed by ObjectIn/OutputStream
   int primFieldSize = -1;  // -1 if not yet calculated
   int objectFieldCount;
+
+  Method readObjectMethod;
+  Method readResolveMethod;
+  boolean realClassIsSerializable;
+  boolean realClassIsExternalizable;
+  ObjectStreamField[] fieldMapping;
+  Class firstNonSerializableParent;
 
   boolean isProxyClass = false;
 
Index: java/io/ObjectStreamField.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectStreamField.java,v
retrieving revision 1.7
diff -u -b -B -r1.7 ObjectStreamField.java
--- java/io/ObjectStreamField.java	20 Dec 2003 22:36:02 -0000	1.7
+++ java/io/ObjectStreamField.java	6 Feb 2004 13:27:00 -0000
@@ -38,6 +38,8 @@
 
 package java.io;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 import gnu.java.lang.reflect.TypeSignature;
 
 /**
@@ -54,6 +56,14 @@
   private boolean unshared;
   private boolean persistent = false;
   private boolean toset = true;
+  private Field field;
+
+  ObjectStreamField (Field field)
+  {
+    this (field.getName(), field.getType());
+    this.field = field;
+    toset = !Modifier.isFinal(field.getModifiers());
+  }
 
   /**
    * This constructor creates an ObjectStreamField instance 
@@ -105,7 +115,6 @@
       }
     catch(ClassNotFoundException e)
       {
-        type = Object.class; //FIXME: ???
       }
   }
   
@@ -128,7 +137,6 @@
       }
     catch(ClassNotFoundException e)
       {
-        type = Object.class; // ALSO FIXME 
       }
   }
 
@@ -176,7 +184,7 @@
   public String getTypeString ()
   {
     // use intern()
-    if (this.type.isPrimitive())
+    if (isPrimitive())
       return null;
     return typename.intern();
   }
@@ -225,7 +233,7 @@
    */
   public boolean isPrimitive ()
   {
-    return type.isPrimitive ();
+    return typename.length() == 1;
   }
 
   public int compareTo (Object o)
@@ -299,5 +307,112 @@
   {
     return "ObjectStreamField< " + type + " " + name + " >";
   }
-}
 
+  final void setBooleanField(Object obj, boolean val)
+  {
+      try
+      {
+	  field.setBoolean(obj, val);
+      }
+      catch(IllegalAccessException x)
+      {
+	  throw new InternalError(x.getMessage());
+      }
+  }
+
+  final void setByteField(Object obj, byte val)
+  {
+      try
+      {
+	  field.setByte(obj, val);
+      }
+      catch(IllegalAccessException x)
+      {
+	  throw new InternalError(x.getMessage());
+      }
+  }
+
+  final void setCharField(Object obj, char val)
+  {
+      try
+      {
+	  field.setChar(obj, val);
+      }
+      catch(IllegalAccessException x)
+      {
+	  throw new InternalError(x.getMessage());
+      }
+  }
+
+  final void setShortField(Object obj, short val)
+  {
+      try
+      {
+	  field.setShort(obj, val);
+      }
+      catch(IllegalAccessException x)
+      {
+	  throw new InternalError(x.getMessage());
+      }
+  }
+
+  final void setIntField(Object obj, int val)
+  {
+      try
+      {
+	  field.setInt(obj, val);
+      }
+      catch(IllegalAccessException x)
+      {
+	  throw new InternalError(x.getMessage());
+      }
+  }
+
+  final void setLongField(Object obj, long val)
+  {
+      try
+      {
+	  field.setLong(obj, val);
+      }
+      catch(IllegalAccessException x)
+      {
+	  throw new InternalError(x.getMessage());
+      }
+  }
+
+  final void setFloatField(Object obj, float val)
+  {
+      try
+      {
+	  field.setFloat(obj, val);
+      }
+      catch(IllegalAccessException x)
+      {
+	  throw new InternalError(x.getMessage());
+      }
+  }
+
+  final void setDoubleField(Object obj, double val)
+  {
+      try
+      {
+	  field.setDouble(obj, val);
+      }
+      catch(IllegalAccessException x)
+      {
+	  throw new InternalError(x.getMessage());
+      }
+  }
+
+  final void setObjectField(Object obj, Object val)
+  {
+    try
+      {
+	field.set(obj, val);
+      }
+    catch(IllegalAccessException x)
+      {
+	throw new InternalError(x.getMessage());
+      }
+  }
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]