ObjectStreamClass.java (ensureFieldsSet): New method.

2007-04-25  Andrew Haley  <aph@redhat.com>

	* java/io/ObjectStreamClass.java (ensureFieldsSet): New method.
	(setFields): call ensureFieldsSet.
	(fieldsSet): New field.
	* java/io/ObjectOutputStream.java (writeFields): Call
	osc.ensureFieldsSet().

	* java/io/ObjectInputStream.java (parseContent): Assign the handle
	for a PROXYCLASSDESC immediately after reading the marker.

From-SVN: r124187
This commit is contained in:
Andrew Haley 2007-04-26 14:31:29 +00:00
parent 02cba8dfe4
commit 5c12b59bd8
15 changed files with 46 additions and 2 deletions

View File

@ -223,6 +223,15 @@ public class ObjectInputStream extends InputStream
case TC_PROXYCLASSDESC:
{
if(dump) dumpElementln("PROXYCLASS");
/* GCJ LOCAL */
// The grammar at this point is
// TC_PROXYCLASSDESC newHandle proxyClassDescInfo
// i.e. we have to assign the handle immediately after
// reading the marker.
int handle = assignNewHandle("Dummy proxy");
/* END GCJ LOCAL */
int n_intf = this.realInputStream.readInt();
String[] intfs = new String[n_intf];
for (int i = 0; i < n_intf; i++)
@ -250,7 +259,9 @@ public class ObjectInputStream extends InputStream
new InternalError("Object ctor missing").initCause(x);
}
}
assignNewHandle(osc);
/* GCJ LOCAL */
rememberHandle(osc,handle);
/* END GCJ LOCAL */
if (!is_consumed)
{

View File

@ -1211,11 +1211,17 @@ public class ObjectOutputStream extends OutputStream
}
/* GCJ LOCAL */
// writes out FIELDS of OBJECT for the specified ObjectStreamClass.
// FIELDS are already in canonical order.
// FIELDS are already supposed already to be in canonical order, but
// under some circumstances (to do with Proxies) this isn't the
// case, so we call ensureFieldsSet().
private void writeFields(Object obj, ObjectStreamClass osc)
throws IOException
{
osc.ensureFieldsSet(osc.forClass());
/* END GCJ LOCAL */
ObjectStreamField[] fields = osc.fields;
boolean oldmode = setBlockDataMode(false);

View File

@ -654,11 +654,29 @@ outer:
flags |= ObjectStreamConstants.SC_ENUM;
}
/* GCJ LOCAL */
// FIXME: This is a workaround for a fairly obscure bug that happens
// when reading a Proxy and then writing it back out again. The
// result is that the ObjectStreamClass doesn't have its fields set,
// generating a NullPointerException. Rather than this kludge we
// should probably fix the real bug, but it would require a fairly
// radical reorganization to do so.
final void ensureFieldsSet(Class cl)
{
if (! fieldsSet)
setFields(cl);
}
/* END GCJ LOCAL */
// Sets fields to be a sorted array of the serializable fields of
// clazz.
private void setFields(Class cl)
{
/* GCJ LOCAL */
fieldsSet = true;
/* END GCJ LOCAL */
SetAccessibleAction setAccessible = new SetAccessibleAction();
if (!isSerializable() || isExternalizable() || isEnum())
@ -1094,6 +1112,11 @@ outer:
boolean isProxyClass = false;
/* GCJ LOCAL */
// True after setFields() has been called
private boolean fieldsSet = false;
/* END GCJ LOCAL */
// This is probably not necessary because this class is special cased already
// but it will avoid showing up as a discrepancy when comparing SUIDs.
private static final long serialVersionUID = -6120832682080437368L;

View File

@ -57,6 +57,9 @@ private:
void cacheMethods();
ObjectStreamClass(::java::lang::Class *);
void setFlags(::java::lang::Class *);
public: // actually package-private
virtual void ensureFieldsSet(::java::lang::Class *);
private:
void setFields(::java::lang::Class *);
jlong getClassUID(::java::lang::Class *);
public: // actually package-private
@ -105,6 +108,7 @@ private:
public: // actually package-private
jboolean isProxyClass;
private:
jboolean fieldsSet;
static const jlong serialVersionUID = -6120832682080437368LL;
public:
static ::java::lang::Class class$;