This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
FYI: ObjectStream fix for shadowed fields
- From: Mark Wielaard <mark at klomp dot org>
- To: java-patches at gcc dot gnu dot org
- Date: 14 Mar 2003 12:50:40 +0100
- Subject: FYI: ObjectStream fix for shadowed fields
- Organization:
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 ()
{