ObjectOutputStream.java: Add DEBUG statements everywhere.
2004-06-21 Andrew Haley <aph@redhat.com> * java/io/ObjectOutputStream.java: Add DEBUG statements everywhere. (dumpElementln): New method. (depth): New field. * java/io/ObjectInputStream.java (currentClassLoader): Make native. (callersClassLoader): New field. (depth): New field. (readObject): ENDBLOCKDATA is generated if the class has a write method, not if it has a read method. (readObject): Save and restore this.currentObject and this.currentObjectStreamClass around calls to callReadMethod(). * java/io/natObjectInputStream.cc (getCallersClassLoader): New method. From-SVN: r83440
This commit is contained in:
parent
413ed876c5
commit
deb3d52fec
4 changed files with 178 additions and 38 deletions
|
@ -1,3 +1,20 @@
|
|||
2004-06-21 Andrew Haley <aph@redhat.com>
|
||||
|
||||
* java/io/ObjectOutputStream.java: Add DEBUG statements
|
||||
everywhere.
|
||||
(dumpElementln): New method.
|
||||
(depth): New field.
|
||||
* java/io/ObjectInputStream.java
|
||||
(currentClassLoader): Make native.
|
||||
(callersClassLoader): New field.
|
||||
(depth): New field.
|
||||
(readObject): ENDBLOCKDATA is generated if the class has a write
|
||||
method, not if it has a read method.
|
||||
(readObject): Save and restore this.currentObject and
|
||||
this.currentObjectStreamClass around calls to callReadMethod().
|
||||
* java/io/natObjectInputStream.cc (getCallersClassLoader): New
|
||||
method.
|
||||
|
||||
2004-06-18 Andreas Tobler <a.tobler@schweiz.ch>
|
||||
|
||||
* testsuite/libjava.jni/jni.exp (gcj_jni_test_one): Add lgcc_s for
|
||||
|
|
|
@ -38,20 +38,24 @@ exception statement from your version. */
|
|||
|
||||
package java.io;
|
||||
|
||||
import gnu.classpath.Configuration;
|
||||
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.security.PrivilegedAction;
|
||||
import java.security.AccessController;
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
import gnu.java.io.ObjectIdentityWrapper;
|
||||
import gnu.java.lang.reflect.TypeSignature;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import gnu.classpath.Configuration;
|
||||
|
||||
public class ObjectInputStream extends InputStream
|
||||
implements ObjectInput, ObjectStreamConstants
|
||||
{
|
||||
|
@ -120,6 +124,15 @@ public class ObjectInputStream extends InputStream
|
|||
*/
|
||||
public final Object readObject() throws ClassNotFoundException, IOException
|
||||
{
|
||||
if (callersClassLoader == null)
|
||||
{
|
||||
callersClassLoader = getCallersClassLoader ();
|
||||
if (Configuration.DEBUG && dump)
|
||||
{
|
||||
dumpElementln ("CallersClassLoader = " + callersClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.useSubclassMethod)
|
||||
return readObjectOverride();
|
||||
|
||||
|
@ -134,6 +147,9 @@ public class ObjectInputStream extends InputStream
|
|||
this.isDeserializing = true;
|
||||
|
||||
byte marker = this.realInputStream.readByte();
|
||||
|
||||
depth += 2;
|
||||
|
||||
if(dump) dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " ");
|
||||
|
||||
try
|
||||
|
@ -151,9 +167,9 @@ public class ObjectInputStream extends InputStream
|
|||
case TC_BLOCKDATALONG:
|
||||
{
|
||||
if (marker == TC_BLOCKDATALONG)
|
||||
if(dump) dumpElementln("BLOCKDATALONG");
|
||||
{ if(dump) dumpElementln("BLOCKDATALONG"); }
|
||||
else
|
||||
if(dump) dumpElementln("BLOCKDATA");
|
||||
{ if(dump) dumpElementln("BLOCKDATA"); }
|
||||
readNextBlock(marker);
|
||||
throw new StreamCorruptedException("Unexpected blockData");
|
||||
}
|
||||
|
@ -319,6 +335,9 @@ public class ObjectInputStream extends InputStream
|
|||
Object obj = newObject(clazz, osc.firstNonSerializableParent);
|
||||
|
||||
int handle = assignNewHandle(obj);
|
||||
Object prevObject = this.currentObject;
|
||||
ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
|
||||
|
||||
this.currentObject = obj;
|
||||
ObjectStreamClass[] hierarchy =
|
||||
inputGetObjectStreamClasses(clazz);
|
||||
|
@ -341,34 +360,42 @@ public class ObjectInputStream extends InputStream
|
|||
boolean oldmode = setBlockDataMode(true);
|
||||
callReadMethod(readObjectMethod, this.currentObjectStreamClass.forClass(), obj);
|
||||
setBlockDataMode(oldmode);
|
||||
if(dump) 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() != TC_ENDBLOCKDATA)
|
||||
throw new IOException
|
||||
("No end of block data seen for class with readObject (ObjectInputStream) method.");
|
||||
if(dump) dumpElementln("yes");
|
||||
}
|
||||
catch (EOFException e)
|
||||
{
|
||||
if(dump) dumpElementln("no, got EOFException");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
if(dump) dumpElementln("no, got IOException");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
readFields(obj, currentObjectStreamClass);
|
||||
}
|
||||
|
||||
if (this.currentObjectStreamClass.hasWriteMethod())
|
||||
{
|
||||
if(dump) 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() != TC_ENDBLOCKDATA)
|
||||
throw new IOException
|
||||
("No end of block data seen for class with readObject (ObjectInputStream) method.");
|
||||
if(dump) dumpElementln("yes");
|
||||
}
|
||||
// catch (EOFException e)
|
||||
// {
|
||||
// if(dump) dumpElementln("no, got EOFException");
|
||||
// }
|
||||
catch (IOException e)
|
||||
{
|
||||
if(dump) dumpElementln("no, got IOException");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.currentObject = null;
|
||||
this.currentObjectStreamClass = null;
|
||||
this.currentObject = prevObject;
|
||||
this.currentObjectStreamClass = prevObjectStreamClass;
|
||||
ret_val = processResolution(osc, obj, handle);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -397,6 +424,8 @@ public class ObjectInputStream extends InputStream
|
|||
|
||||
this.isDeserializing = was_deserializing;
|
||||
|
||||
depth -= 2;
|
||||
|
||||
if (! was_deserializing)
|
||||
{
|
||||
if (validators.size() > 0)
|
||||
|
@ -710,7 +739,7 @@ public class ObjectInputStream extends InputStream
|
|||
protected Class resolveClass(ObjectStreamClass osc)
|
||||
throws ClassNotFoundException, IOException
|
||||
{
|
||||
return Class.forName(osc.getName(), true, currentLoader());
|
||||
return Class.forName(osc.getName(), true, callersClassLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1802,11 +1831,9 @@ public class ObjectInputStream extends InputStream
|
|||
* @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 ();
|
||||
}
|
||||
private static native ClassLoader currentClassLoader (SecurityManager sm);
|
||||
|
||||
private native ClassLoader getCallersClassLoader();
|
||||
|
||||
private void callReadMethod (Method readObject, Class klass, Object obj) throws IOException
|
||||
{
|
||||
|
@ -1864,6 +1891,11 @@ public class ObjectInputStream extends InputStream
|
|||
|
||||
private static boolean dump = false && Configuration.DEBUG;
|
||||
|
||||
private ClassLoader callersClassLoader;
|
||||
|
||||
// The nesting depth for debugging output
|
||||
private int depth = 0;
|
||||
|
||||
private void dumpElement (String msg)
|
||||
{
|
||||
System.out.print(msg);
|
||||
|
@ -1872,6 +1904,9 @@ public class ObjectInputStream extends InputStream
|
|||
private void dumpElementln (String msg)
|
||||
{
|
||||
System.out.println(msg);
|
||||
for (int i = 0; i < depth; i++)
|
||||
System.out.print (" ");
|
||||
System.out.print (Thread.currentThread() + ": ");
|
||||
}
|
||||
|
||||
static
|
||||
|
|
|
@ -144,6 +144,13 @@ public class ObjectOutputStream extends OutputStream
|
|||
protocolVersion = defaultProtocolVersion;
|
||||
useSubclassMethod = false;
|
||||
writeStreamHeader();
|
||||
|
||||
if (Configuration.DEBUG)
|
||||
{
|
||||
String val = System.getProperty("gcj.dumpobjects");
|
||||
if (val != null && !val.equals(""))
|
||||
dump = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -172,10 +179,18 @@ public class ObjectOutputStream extends OutputStream
|
|||
{
|
||||
if (useSubclassMethod)
|
||||
{
|
||||
if (dump)
|
||||
dumpElementln ("WRITE OVERRIDE: " + obj);
|
||||
|
||||
writeObjectOverride(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dump)
|
||||
dumpElementln ("WRITE: " + obj);
|
||||
|
||||
depth += 2;
|
||||
|
||||
boolean was_serializing = isSerializing;
|
||||
boolean old_mode = setBlockDataMode(false);
|
||||
try
|
||||
|
@ -318,6 +333,8 @@ public class ObjectOutputStream extends OutputStream
|
|||
|
||||
if (obj instanceof Serializable)
|
||||
{
|
||||
Object prevObject = this.currentObject;
|
||||
ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
|
||||
currentObject = obj;
|
||||
ObjectStreamClass[] hierarchy =
|
||||
ObjectStreamClass.getObjectStreamClasses(clazz);
|
||||
|
@ -329,17 +346,25 @@ public class ObjectOutputStream extends OutputStream
|
|||
fieldsAlreadyWritten = false;
|
||||
if (currentObjectStreamClass.hasWriteMethod())
|
||||
{
|
||||
if (dump)
|
||||
dumpElementln ("WRITE METHOD CALLED FOR: " + obj);
|
||||
setBlockDataMode(true);
|
||||
callWriteMethod(obj, currentObjectStreamClass);
|
||||
setBlockDataMode(false);
|
||||
realOutput.writeByte(TC_ENDBLOCKDATA);
|
||||
if (dump)
|
||||
dumpElementln ("WRITE ENDBLOCKDATA FOR: " + obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dump)
|
||||
dumpElementln ("WRITE FIELDS CALLED FOR: " + obj);
|
||||
writeFields(obj, currentObjectStreamClass);
|
||||
}
|
||||
}
|
||||
|
||||
currentObject = null;
|
||||
currentObjectStreamClass = null;
|
||||
this.currentObject = prevObject;
|
||||
this.currentObjectStreamClass = prevObjectStreamClass;
|
||||
currentPutField = null;
|
||||
break;
|
||||
}
|
||||
|
@ -360,12 +385,22 @@ public class ObjectOutputStream extends OutputStream
|
|||
setBlockDataMode(false);
|
||||
try
|
||||
{
|
||||
if (Configuration.DEBUG)
|
||||
{
|
||||
e.printStackTrace(System.out);
|
||||
}
|
||||
writeObject(e);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
throw new StreamCorruptedException
|
||||
("Exception " + ioe + " thrown while exception was being written to stream.");
|
||||
StreamCorruptedException ex =
|
||||
new StreamCorruptedException
|
||||
(ioe + " thrown while exception was being written to stream.");
|
||||
if (Configuration.DEBUG)
|
||||
{
|
||||
ex.printStackTrace(System.out);
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
|
||||
reset (true);
|
||||
|
@ -375,6 +410,10 @@ public class ObjectOutputStream extends OutputStream
|
|||
{
|
||||
isSerializing = was_serializing;
|
||||
setBlockDataMode(old_mode);
|
||||
depth -= 2;
|
||||
|
||||
if (dump)
|
||||
dumpElementln ("END: " + obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1171,6 +1210,9 @@ public class ObjectOutputStream extends OutputStream
|
|||
field_name = fields[i].getName();
|
||||
type = fields[i].getType();
|
||||
|
||||
if (dump)
|
||||
dumpElementln ("WRITE FIELD: " + field_name + " type=" + type);
|
||||
|
||||
if (type == Boolean.TYPE)
|
||||
realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name));
|
||||
else if (type == Byte.TYPE)
|
||||
|
@ -1512,6 +1554,14 @@ public class ObjectOutputStream extends OutputStream
|
|||
return m;
|
||||
}
|
||||
|
||||
private void dumpElementln (String msg)
|
||||
{
|
||||
for (int i = 0; i < depth; i++)
|
||||
System.out.print (" ");
|
||||
System.out.print (Thread.currentThread() + ": ");
|
||||
System.out.println(msg);
|
||||
}
|
||||
|
||||
// this value comes from 1.2 spec, but is used in 1.1 as well
|
||||
private final static int BUFFER_SIZE = 1024;
|
||||
|
||||
|
@ -1534,6 +1584,12 @@ public class ObjectOutputStream extends OutputStream
|
|||
private int protocolVersion;
|
||||
private boolean useSubclassMethod;
|
||||
|
||||
// The nesting depth for debugging output
|
||||
private int depth = 0;
|
||||
|
||||
// Set if we're generating debugging dumps
|
||||
private boolean dump = false;
|
||||
|
||||
static
|
||||
{
|
||||
if (Configuration.INIT_LOAD_LIBRARY)
|
||||
|
|
|
@ -19,6 +19,8 @@ details. */
|
|||
#include <java/lang/Class.h>
|
||||
#include <java/lang/reflect/Modifier.h>
|
||||
#include <java/lang/reflect/Method.h>
|
||||
#include <java/lang/ArrayIndexOutOfBoundsException.h>
|
||||
#include <java/lang/SecurityManager.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <java/lang/System.h>
|
||||
|
@ -69,3 +71,33 @@ java::io::ObjectInputStream::callConstructor (jclass klass, jobject obj)
|
|||
+ m->offset);
|
||||
_Jv_CallAnyMethodA (obj, JvPrimClass (void), meth, false, arg_types, NULL);
|
||||
}
|
||||
|
||||
java::lang::ClassLoader*
|
||||
java::io::ObjectInputStream::getCallersClassLoader ()
|
||||
{
|
||||
java::lang::ClassLoader *loader = NULL;
|
||||
gnu::gcj::runtime::StackTrace *t
|
||||
= new gnu::gcj::runtime::StackTrace(4);
|
||||
java::lang::Class *klass = NULL;
|
||||
try
|
||||
{
|
||||
for (int i = 2; !klass; i++)
|
||||
{
|
||||
klass = t->classAt (i);
|
||||
}
|
||||
loader = klass->getClassLoaderInternal();
|
||||
}
|
||||
catch (::java::lang::ArrayIndexOutOfBoundsException *e)
|
||||
{
|
||||
// FIXME: RuntimeError
|
||||
}
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
java::lang::ClassLoader*
|
||||
java::io::ObjectInputStream::currentClassLoader (::java::lang::SecurityManager *sm)
|
||||
{
|
||||
return sm->currentClassLoader ();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue