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]

ObjectStreamClass merge with Classpath


Hi,

The following merges java.io.ObjectStreamClass with the Classpath
version. It does make one new Mauve test succeed (ProxyTest), but it
does not fix the two Mauve regressions. I do now know why they fail
though (Class.getDeclaredMethod("<clinit>") has been - correctly -
changed to throw NoSuchMethodException). I will submit a patch for this
later.

2003-01-03  Mark Wielaard  <mark@klomp.org>

	Merge with Classpath:
	* java/io/ObjectStreamClass.java (lookup): Split method and call
	lookupForClassObject().
	(lookupForClassObject): New method.
	(isProxyClass): New field.
	(setClass): Set isProxyClass, add object to classLookupTable, set
	superClass and calculateOffsets.
	(ObjectStreamClass): Set isProxyClass. Only set uid when Serializable
	and not a proxy class.
	(setFields): Set accessible treu for serialPersistentFields.
	(getClassUID): Same for suid. And check if suid is of type long.
	(hasClassInitializer): Don't throw NoSuchMethodError.

OK for branch and mainline?

Cheers,

Mark
Index: java/io/ObjectStreamClass.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectStreamClass.java,v
retrieving revision 1.9
diff -u -r1.9 ObjectStreamClass.java
--- java/io/ObjectStreamClass.java	22 Jan 2002 22:40:14 -0000	1.9
+++ java/io/ObjectStreamClass.java	3 Jan 2003 23:57:55 -0000
@@ -1,6 +1,6 @@
 /* ObjectStreamClass.java -- Class used to write class information
    about serialized objects.
-   Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2003  Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -44,6 +44,7 @@
 import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
 import java.security.DigestOutputStream;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -76,6 +77,19 @@
     if (! (Serializable.class).isAssignableFrom (cl))
       return null;
 
+    return lookupForClassObject (cl);
+  }
+
+  /**
+   * This lookup for internal use by ObjectOutputStream.  Suppose
+   * we have a java.lang.Class object C for class A, though A is not
+   * serializable, but it's okay to serialize C.
+   */
+  static ObjectStreamClass lookupForClassObject (Class cl)
+  {
+    if (cl == null)
+      return null;
+
     ObjectStreamClass osc = (ObjectStreamClass)classLookupTable.get (cl);
 
     if (osc != null)
@@ -260,22 +274,29 @@
   void setClass (Class cl) throws InvalidClassException
   {
     this.clazz = cl;
+
     long class_uid = getClassUID (cl);
     if (uid == 0)
+      uid = class_uid;
+    else
       {
-       uid = class_uid;
-       return;
-      }
-    
-    // Check that the actual UID of the resolved class matches the UID from 
-    // the stream.    
-    if (uid != class_uid)
-      {
-       String msg = cl + 
-	 ": Local class not compatible: stream serialVersionUID="
-	 + uid + ", local serialVersionUID=" + class_uid;
-       throw new InvalidClassException (msg);
+	// Check that the actual UID of the resolved class matches the UID from 
+	// the stream.    
+	if (uid != class_uid)
+	  {
+	    String msg = cl + 
+	      ": Local class not compatible: stream serialVersionUID="
+	      + uid + ", local serialVersionUID=" + class_uid;
+	    throw new InvalidClassException (msg);
+	  }
       }
+
+    isProxyClass = clazz != null && Proxy.isProxyClass (clazz);
+    ObjectStreamClass osc = (ObjectStreamClass)classLookupTable.get (clazz);
+    if (osc == null)
+      classLookupTable.put (clazz, this);
+    superClass = lookupForClassObject (clazz.getSuperclass ());
+    calculateOffsets ();
   }
 
   void setSuperclass (ObjectStreamClass osc)
@@ -328,12 +349,15 @@
   {
     uid = 0;
     flags = 0;
+    isProxyClass = Proxy.isProxyClass (cl);
 
     clazz = cl;
     name = cl.getName ();
     setFlags (cl);
     setFields (cl);
-    uid = getClassUID (cl);
+    // to those class nonserializable, its uid field is 0
+    if ( (Serializable.class).isAssignableFrom (cl) && !isProxyClass)
+      uid = getClassUID (cl);
     superClass = lookup (cl.getSuperclass ());
   }
 
@@ -377,6 +401,7 @@
     {
       Field serialPersistentFields
 	= cl.getDeclaredField ("serialPersistentFields");
+      serialPersistentFields.setAccessible(true);
       int modifiers = serialPersistentFields.getModifiers ();
 
       if (Modifier.isStatic (modifiers)
@@ -427,26 +452,27 @@
   {
     try
     {
+      // Use getDeclaredField rather than getField, since serialVersionUID
+      // may not be public AND we only want the serialVersionUID of this
+      // class, not a superclass or interface.
       Field suid = cl.getDeclaredField ("serialVersionUID");
+      suid.setAccessible(true);
       int modifiers = suid.getModifiers ();
 
-      if (Modifier.isStatic (modifiers) && Modifier.isFinal (modifiers))
-	return suid.getLong (null);	  
+      if (Modifier.isStatic (modifiers)
+	  && Modifier.isFinal (modifiers)
+	  && suid.getType() == Long.TYPE)
+	return suid.getLong (null);
     }
     catch (NoSuchFieldException ignore)
-    {
-    }
+    {}
     catch (IllegalAccessException ignore)
-    {
-    }
+    {}
 
     // cl didn't define serialVersionUID, so we have to compute it
     try
     {
-      MessageDigest md = null;
-      DigestOutputStream digest_out = null;
-      DataOutputStream data_out = null;
-
+      MessageDigest md;
       try 
 	{
 	  md = MessageDigest.getInstance ("SHA");
@@ -459,8 +485,10 @@
 	  md = MessageDigest.getInstance ("SHA");
 	}
 
-      digest_out = new DigestOutputStream (nullOutputStream, md);
-      data_out = new DataOutputStream (digest_out);
+      DigestOutputStream digest_out =
+	new DigestOutputStream (nullOutputStream, md);
+      DataOutputStream data_out = new DataOutputStream (digest_out);
+
       data_out.writeUTF (cl.getName ());
 
       int modifiers = cl.getModifiers ();
@@ -497,17 +525,7 @@
       }
 
       // write class initializer method if present
-      boolean has_init;
-      try
-      {
-	has_init = hasClassInitializer (cl);
-      }
-      catch (NoSuchMethodError e)
-      {
-	has_init = false;
-      }
-
-      if (has_init)
+      if (hasClassInitializer (cl))
       {
 	data_out.writeUTF ("<clinit>");
 	data_out.writeInt (Modifier.STATIC);
@@ -564,11 +582,11 @@
     catch (NoSuchAlgorithmException e)
     {
       throw new RuntimeException ("The SHA algorithm was not found to use in computing the Serial Version UID for class "
-				  + cl.getName ());
+				  + cl.getName (), e);
     }
     catch (IOException ioe)
     {
-      throw new RuntimeException (ioe.getMessage ());
+      throw new RuntimeException (ioe);
     }
   }
 
@@ -582,6 +600,7 @@
 	// Use getDeclaredField rather than getField for the same reason
 	// as above in getDefinedSUID.
 	Field f = clazz.getDeclaredField ("getSerialPersistentFields");
+	f.setAccessible(true);
 	o = (ObjectStreamField[])f.get (null);
       }
     catch (java.lang.NoSuchFieldException e)
@@ -597,21 +616,23 @@
 
   // Returns true if CLAZZ has a static class initializer
   // (a.k.a. <clinit>).
-  //
-  // A NoSuchMethodError is raised if CLAZZ has no such method.
   private static boolean hasClassInitializer (Class clazz)
-    throws java.lang.NoSuchMethodError
   {
     Method m = null;
 
     try
       {
+	/*
+	 * There exists a problem here, according to the spec
+	 * clazz.getDeclaredMethod ("<clinit>", classArgs);
+	 * will always throw NoSuchMethodException, even if the static 
+	 * intializer does exist.
+	 */
 	Class classArgs[] = {};
 	m = clazz.getDeclaredMethod ("<clinit>", classArgs);
       }
     catch (java.lang.NoSuchMethodException e)
       {
-	throw new java.lang.NoSuchMethodError ();
       }
 
     return m != null;
@@ -640,9 +661,12 @@
   int primFieldSize = -1;  // -1 if not yet calculated
   int objectFieldCount;
 
+  boolean isProxyClass = false;
+
   // 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;
+
 }
 
 

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