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: ObjectStream fix for shadowed fields


Hi,

Jeroen his paperwork came through so I am applying this patch to branch
and mainline (and Classpath if subversions.gnu.org ever completes a CVS
update...). It cleans up the code a little bit and more importantly it
fixes the bug (shown by Mauve and seen in actual code) we had when a
class was shadowing a private field of one of the super classes.

2003-03-14  Jeroen Frijters  <jeroen at sumatra dot nl>
                                                                                
        * java/io/ObjectInputStream.java (readObject): Cleaned up the class
        hierarchy loop.
        (readFields(Object,ObjectStreamField[],boolean)): Changed argument
        list to Object,ObjectStreamClass, moved callReadMethod code up into
        readObject and added Class argument to all setXxxField calls.
        (callReadMethod): Changed Class argument to ObjectStreamClass to be
        consistent with ObjectOutputStream and to facilitate caching the
        Method in the future.
        (setBooleanField): Added Class argument.
        (setByteField): Likewise.
        (setCharField): Likewise.
        (setDoubleField): Likewise.
        (setFloatField): Likewise.
        (setIntField): Likewise.
        (setLongField): Likewise.
        (setShortField): Likewise.
        (setObjectField): Likewise.
        * java/io/ObjectOutputStream.java (writeObject): Cleaned up the
        class hierarchy loop.
        (defaultWriteObject): Call writeFields with new argument list.
        (writeFields(Object,ObjectStreamField[],boolean): Changed argument
        list to Object,ObjectStreamClass, moved callWriteMethod up into
        writeObject and added Class argument to all getXxxField calls.
        (callWriteMethod): Added ObjectStreamClass argument to be able to
        get the proper class to call getMethod on (each class can have (or
        not have) its own writeObject method).
        (getBooleanField): Added Class argument.
        (getByteField): Likewise.
        (getCharField): Likewise.
        (getDoubleField): Likewise.
        (getFloatField): Likewise.
        (getIntField): Likewise.
        (getLongField): Likewise.
        (getShortField): Likewise.
        (getObjectField): Likewise.
        * java/io/ObjectStreamClass.java (hasReadMethod): Added method to
        facilitate caching the Method object in the future.

Cheers,

Mark
Index: java/io/ObjectInputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectInputStream.java,v
retrieving revision 1.15
diff -u -r1.15 ObjectInputStream.java
--- java/io/ObjectInputStream.java	1 Mar 2003 15:05:46 -0000	1.15
+++ java/io/ObjectInputStream.java	14 Mar 2003 11:46:56 -0000
@@ -368,35 +368,24 @@
 	      ObjectStreamClass[] hierarchy =
 		ObjectStreamClass.getObjectStreamClasses (clazz);
 	      
-	      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)
+		  
+		  if (this.currentObjectStreamClass.hasReadMethod())
 		    {
+		      fieldsAlreadyRead = false;
+		      boolean oldmode = setBlockDataMode (true);
+		      callReadMethod (obj, this.currentObjectStreamClass);
+		      setBlockDataMode (oldmode);
 		      dumpElement ("ENDBLOCKDATA? ");
 		      try
 			{
@@ -415,6 +404,10 @@
 			  dumpElementln ("no, got IOException");
 			}
 		    }
+		  else
+		    {
+		      readFields (obj, currentObjectStreamClass);
+		    }
 		}
 
 	      this.currentObject = null;
@@ -487,9 +480,7 @@
       throw new NotActiveException ("defaultReadObject called but fields already read from stream (by defaultReadObject or readFields)");
 
     boolean oldmode = setBlockDataMode(false);
-    readFields (this.currentObject,
-		this.currentObjectStreamClass.fields,
-		false, this.currentObjectStreamClass);
+    readFields (this.currentObject, this.currentObjectStreamClass);
     setBlockDataMode(oldmode);
 
     fieldsAlreadyRead = true;
@@ -1220,20 +1211,10 @@
   }
 
 
-  private void readFields (Object obj, ObjectStreamField[] stream_fields,
-			   boolean call_read_method,
-			   ObjectStreamClass stream_osc)
+  private void readFields (Object obj, ObjectStreamClass stream_osc)
     throws ClassNotFoundException, IOException
   {
-    if (call_read_method)
-      {
-	fieldsAlreadyRead = false;
-	boolean oldmode = setBlockDataMode (true);
-	callReadMethod (obj, stream_osc.forClass ());
-	setBlockDataMode (oldmode);
-	return;
-      }
-
+    ObjectStreamField[] stream_fields = stream_osc.fields;
     ObjectStreamField[] real_fields =
       ObjectStreamClass.lookup (stream_osc.forClass ()).fields;
 
@@ -1299,7 +1280,7 @@
 		if (!default_initialize && set_value)
 		  dumpElementln ("  " + field_name + ": " + value);
 		if (set_value)
-		  setBooleanField (obj, field_name, value);
+		  setBooleanField (obj, stream_osc.forClass (), field_name, value);
 	      }
 	    else if (type == Byte.TYPE)
 	      {
@@ -1308,7 +1289,7 @@
 		if (!default_initialize && set_value)
 		  dumpElementln ("  " + field_name + ": " + value);
 		if (set_value)
-		  setByteField (obj, field_name, value);
+		  setByteField (obj, stream_osc.forClass (), field_name, value);
 	      }
 	    else if (type == Character.TYPE)
 	      {
@@ -1317,7 +1298,7 @@
 		if (!default_initialize && set_value)
 		  dumpElementln ("  " + field_name + ": " + value);
 		if (set_value)
-		  setCharField (obj, field_name, value);
+		  setCharField (obj, stream_osc.forClass (), field_name, value);
 	      }
 	    else if (type == Double.TYPE)
 	      {
@@ -1326,7 +1307,7 @@
 		if (!default_initialize && set_value)
 		  dumpElementln ("  " + field_name + ": " + value);
 		if (set_value)
-		  setDoubleField (obj, field_name, value);
+		  setDoubleField (obj, stream_osc.forClass (), field_name, value);
 	      }
 	    else if (type == Float.TYPE)
 	      {
@@ -1335,7 +1316,7 @@
 		if (!default_initialize && set_value)
 		  dumpElementln ("  " + field_name + ": " + value);
 		if (set_value)
-		  setFloatField (obj, field_name, value);
+		  setFloatField (obj, stream_osc.forClass (), field_name, value);
 	      }
 	    else if (type == Integer.TYPE)
 	      {
@@ -1344,7 +1325,7 @@
 		if (!default_initialize && set_value)
 		  dumpElementln ("  " + field_name + ": " + value);
 		if (set_value)
-		  setIntField (obj, field_name, value);
+		  setIntField (obj, stream_osc.forClass (), field_name, value);
 	      }
 	    else if (type == Long.TYPE)
 	      {
@@ -1353,7 +1334,7 @@
 		if (!default_initialize && set_value)
 		  dumpElementln ("  " + field_name + ": " + value);
 		if (set_value)
-		  setLongField (obj, field_name, value);
+		  setLongField (obj, stream_osc.forClass (), field_name, value);
 	      }
 	    else if (type == Short.TYPE)
 	      {
@@ -1362,14 +1343,14 @@
 		if (!default_initialize && set_value)
 		  dumpElementln ("  " + field_name + ": " + value);
 		if (set_value)
-		  setShortField (obj, field_name, value);
+		  setShortField (obj, stream_osc.forClass (), field_name, value);
 	      }
 	    else
 	      {
 		Object value =
 		  default_initialize ? null : readObject ();
 		if (set_value)
-		  setObjectField (obj, field_name,
+		  setObjectField (obj, stream_osc.forClass (), field_name,
 				  real_field.getTypeString (), value);
 	      }
 	  }
@@ -1451,8 +1432,9 @@
     return klass.getDeclaredMethod(name, args);
   }
 
-  private void callReadMethod (Object obj, Class klass) throws IOException
+  private void callReadMethod (Object obj, ObjectStreamClass osc) throws IOException
   {
+    Class klass = osc.forClass();
     try
       {
 	Class classArgs[] = {ObjectInputStream.class};
@@ -1486,12 +1468,11 @@
 
   private native void callConstructor (Class clazz, Object obj);
 
-  private void setBooleanField (Object obj, String field_name,
+  private void setBooleanField (Object obj, Class klass, String field_name,
 				boolean val)
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	f.setAccessible(true);
 	f.setBoolean (obj, val);
@@ -1501,12 +1482,11 @@
       }    
   }
 
-  private void setByteField (Object obj, String field_name,
+  private void setByteField (Object obj, Class klass, String field_name,
 			     byte val)
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	f.setAccessible(true);
 	f.setByte (obj, val);
@@ -1516,12 +1496,11 @@
       }    
   }
 
-  private void setCharField (Object obj, String field_name,
+  private void setCharField (Object obj, Class klass, String field_name,
 			     char val)
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	f.setAccessible(true);
 	f.setChar (obj, val);
@@ -1531,12 +1510,11 @@
       }    
   }
 
-  private void setDoubleField (Object obj, String field_name,
+  private void setDoubleField (Object obj, Class klass, String field_name,
 			       double val)
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	f.setAccessible(true);
 	f.setDouble (obj, val);
@@ -1546,12 +1524,11 @@
       }    
   }
 
-  private void setFloatField (Object obj, String field_name,
+  private void setFloatField (Object obj, Class klass, String field_name,
 			      float val)
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	f.setAccessible(true);
 	f.setFloat (obj, val);
@@ -1561,12 +1538,11 @@
       }    
   }
 
-  private void setIntField (Object obj, String field_name,
+  private void setIntField (Object obj, Class klass, String field_name,
 			    int val)
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	f.setAccessible(true);
 	f.setInt (obj, val);
@@ -1577,12 +1553,11 @@
   }
 
 
-  private void setLongField (Object obj, String field_name,
+  private void setLongField (Object obj, Class klass, String field_name,
 			     long val)
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	f.setAccessible(true);
 	f.setLong (obj, val);
@@ -1593,12 +1568,11 @@
   }
 
 
-  private void setShortField (Object obj, String field_name,
+  private void setShortField (Object obj, Class klass, String field_name,
 			      short val)
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	f.setAccessible(true);
 	f.setShort (obj, val);
@@ -1609,12 +1583,11 @@
   }
 
 
-  private void setObjectField (Object obj, String field_name, String type_code,
+  private void setObjectField (Object obj, Class klass, String field_name, String type_code,
 			       Object val)
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	f.setAccessible(true);
 	// FIXME: We should check the type_code here
Index: java/io/ObjectOutputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectOutputStream.java,v
retrieving revision 1.12
diff -u -r1.12 ObjectOutputStream.java
--- java/io/ObjectOutputStream.java	1 Mar 2003 15:05:46 -0000	1.12
+++ java/io/ObjectOutputStream.java	14 Mar 2003 11:46:56 -0000
@@ -354,16 +354,20 @@
 		ObjectStreamClass[] hierarchy =
 		  ObjectStreamClass.getObjectStreamClasses (clazz);
 
-		boolean has_write;
 		for (int i=0; i < hierarchy.length; i++)
 		  {
 		    currentObjectStreamClass = hierarchy[i];
 
 		    fieldsAlreadyWritten = false;
-		    has_write = currentObjectStreamClass.hasWriteMethod ();
-
-		    writeFields (obj, currentObjectStreamClass.fields,
-				 has_write);
+		    if (currentObjectStreamClass.hasWriteMethod ())
+		      {
+			setBlockDataMode (true);
+			callWriteMethod (obj, currentObjectStreamClass);
+			setBlockDataMode (false);
+			realOutput.writeByte (TC_ENDBLOCKDATA);
+		      }
+		    else
+		      writeFields (obj, currentObjectStreamClass);
 		  }
 
 		currentObject = null;
@@ -424,7 +428,7 @@
     throws IOException, NotActiveException
   {
     markFieldsWritten ();
-    writeFields (currentObject, currentObjectStreamClass.fields, false);
+    writeFields (currentObject, currentObjectStreamClass);
   }
 
 
@@ -1145,22 +1149,12 @@
   }
 
 
-  // writes out FIELDS of OBJECT.  If CALL_WRITE_METHOD is true, use
-  // object's writeObject (ObjectOutputStream), otherwise use default
-  // serialization.  FIELDS are already in canonical order.
-  private void writeFields (Object obj,
-			    ObjectStreamField[] fields,
-			    boolean call_write_method) throws IOException
+  // writes out FIELDS of OBJECT for the specified ObjectStreamClass.
+  // FIELDS are already in canonical order.
+  private void writeFields (Object obj, ObjectStreamClass osc)
+    throws IOException
   {
-    if (call_write_method)
-      {
-	setBlockDataMode (true);
-	callWriteMethod (obj);
-	setBlockDataMode (false);
-	realOutput.writeByte (TC_ENDBLOCKDATA);
-	return;
-      }
-
+    ObjectStreamField[] fields = osc.fields;
     boolean oldmode = setBlockDataMode (false);
     String field_name;
     Class type;
@@ -1170,23 +1164,23 @@
 	type = fields[i].getType ();
 
 	if (type == Boolean.TYPE)
-	  realOutput.writeBoolean (getBooleanField (obj, field_name));
+	  realOutput.writeBoolean (getBooleanField (obj, osc.forClass(), field_name));
 	else if (type == Byte.TYPE)
-	  realOutput.writeByte (getByteField (obj, field_name));
+	  realOutput.writeByte (getByteField (obj, osc.forClass(), field_name));
 	else if (type == Character.TYPE)
-	  realOutput.writeChar (getCharField (obj, field_name));
+	  realOutput.writeChar (getCharField (obj, osc.forClass(), field_name));
 	else if (type == Double.TYPE)
-	  realOutput.writeDouble (getDoubleField (obj, field_name));
+	  realOutput.writeDouble (getDoubleField (obj, osc.forClass(), field_name));
 	else if (type == Float.TYPE)
-	  realOutput.writeFloat (getFloatField (obj, field_name));
+	  realOutput.writeFloat (getFloatField (obj, osc.forClass(), field_name));
 	else if (type == Integer.TYPE)
-	  realOutput.writeInt (getIntField (obj, field_name));
+	  realOutput.writeInt (getIntField (obj, osc.forClass(), field_name));
 	else if (type == Long.TYPE)
-	  realOutput.writeLong (getLongField (obj, field_name));
+	  realOutput.writeLong (getLongField (obj, osc.forClass(), field_name));
 	else if (type == Short.TYPE)
-	  realOutput.writeShort (getShortField (obj, field_name));
+	  realOutput.writeShort (getShortField (obj, osc.forClass(), field_name));
 	else
-	  writeObject (getObjectField (obj, field_name,
+	  writeObject (getObjectField (obj, osc.forClass(), field_name,
 				       fields[i].getTypeString ()));
       }
     setBlockDataMode (oldmode);
@@ -1212,9 +1206,9 @@
   }
 
 
-  private void callWriteMethod (Object obj) throws IOException
+  private void callWriteMethod (Object obj, ObjectStreamClass osc) throws IOException
   {
-    Class klass = obj.getClass ();
+    Class klass = osc.forClass();
     try
       {
 	Class classArgs[] = {ObjectOutputStream.class};
@@ -1243,12 +1237,11 @@
       }
   }
 
-  private boolean getBooleanField (Object obj, String field_name)
+  private boolean getBooleanField (Object obj, Class klass, String field_name)
     throws IOException
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	boolean b = f.getBoolean (obj);
 	return b;
@@ -1259,11 +1252,10 @@
       }    
   }
 
-  private byte getByteField (Object obj, String field_name) throws IOException
+  private byte getByteField (Object obj, Class klass, String field_name) throws IOException
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	byte b = f.getByte (obj);
 	return b;
@@ -1274,11 +1266,10 @@
       }    
   }
 
-  private char getCharField (Object obj, String field_name) throws IOException
+  private char getCharField (Object obj, Class klass, String field_name) throws IOException
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	char b = f.getChar (obj);
 	return b;
@@ -1289,12 +1280,11 @@
       }    
   }
 
-  private double getDoubleField (Object obj, String field_name)
+  private double getDoubleField (Object obj, Class klass, String field_name)
     throws IOException
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	double b = f.getDouble (obj);
 	return b;
@@ -1305,12 +1295,11 @@
       }    
   }
 
-  private float getFloatField (Object obj, String field_name)
+  private float getFloatField (Object obj, Class klass, String field_name)
     throws IOException
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	float b = f.getFloat (obj);
 	return b;
@@ -1321,11 +1310,10 @@
       }    
   }
 
-  private int getIntField (Object obj, String field_name) throws IOException
+  private int getIntField (Object obj, Class klass, String field_name) throws IOException
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	int b = f.getInt (obj);
 	return b;
@@ -1336,11 +1324,10 @@
       }    
   }
 
-  private long getLongField (Object obj, String field_name) throws IOException
+  private long getLongField (Object obj, Class klass, String field_name) throws IOException
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	long b = f.getLong (obj);
 	return b;
@@ -1351,12 +1338,11 @@
       }    
   }
 
-  private short getShortField (Object obj, String field_name)
+  private short getShortField (Object obj, Class klass, String field_name)
     throws IOException
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	short b = f.getShort (obj);
 	return b;
@@ -1367,12 +1353,11 @@
       }    
   }
 
-  private Object getObjectField (Object obj, String field_name,
+  private Object getObjectField (Object obj, Class klass, String field_name,
 				 String type_code) throws IOException
   {
     try
       {
-	Class klass = obj.getClass ();
 	Field f = getField (klass, field_name);
 	Object o = f.get (obj);
 	// FIXME: We should check the type_code here
Index: java/io/ObjectStreamClass.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectStreamClass.java,v
retrieving revision 1.11
diff -u -r1.11 ObjectStreamClass.java
--- java/io/ObjectStreamClass.java	20 Jan 2003 06:46:28 -0000	1.11
+++ java/io/ObjectStreamClass.java	14 Mar 2003 11:46:56 -0000
@@ -194,6 +194,28 @@
 
 
   // 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 ()
   {

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