ObjectOutputStream.java: Add DEBUG statements everywhere.
authorAndrew Haley <aph@redhat.com>
Mon, 21 Jun 2004 16:52:14 +0000 (16:52 +0000)
committerAndrew Haley <aph@gcc.gnu.org>
Mon, 21 Jun 2004 16:52:14 +0000 (16:52 +0000)
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

libjava/ChangeLog
libjava/java/io/ObjectInputStream.java
libjava/java/io/ObjectOutputStream.java
libjava/java/io/natObjectInputStream.cc

index b77c9a9..a08f217 100644 (file)
@@ -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
index 9747699..292f841 100644 (file)
@@ -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);
+                   }
+                 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.
+                         // 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 (EOFException e)
+//                     {
+//                       if(dump) dumpElementln("no, got EOFException");
+//                     }
                      catch (IOException e)
                        {
                          if(dump) dumpElementln("no, got IOException");
                        }
                    }
-                 else
-                   {
-                     readFields(obj, currentObjectStreamClass);
-                   }
                }
 
-             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
index b60f3b6..cc77976 100644 (file)
@@ -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)
index bb3796f..9da4910 100644 (file)
@@ -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 ();
+}
+