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]

Backport of my recent patches to 3.0 branch


This patch backports some parts of my recent patches to the 3.0 branch.
It includes the Class.forName()/ClassLoader fixes/cleanups,
serialization fixes, and the vtable-setting fix/cleanup. I'm checking it
in.

regards

  [ bryce ]


2001-05-06  Bryce McKinlay  <bryce@waitaki.otago.ac.nz>

	* java/lang/Class.h (_Jv_Self): New union type.
	(Class): Manipulate vtable pointer via _Jv_Self union. Thanks to
	Jeff Sturm and Fergus Henderson.

2001-05-06  Bryce McKinlay  <bryce@waitaki.otago.ac.nz>

	Fix PR libgcj/2237:
	* java/io/ObjectStreamClass.java (setClass): Calculate 
	serialVersionUID for local class and compare it against the UID
	from the Object Stream. Throw InvalidClassException upon mismatch.
	(setUID): Renamed to...
	(getClassUID): this. Return the calculated class UID rather than 
	setting uid field directly.
	(getDefinedSUID): Removed.
	* java/io/ObjectInputStream.java (resolveClass): Use the 
	three-argument Class.forName(). 
	* java/io/InvalidClassException.java (toString): Don't include 
	classname in result if it is null.

2001-05-06  Bryce McKinlay  <bryce@waitaki.otago.ac.nz>

	* java/lang/Class.h (forName): Add initialize parameter. Fixes 
	declaration to comply with JDK spec.
	* java/lang/natClass.cc (forName): Correct declaration of the three-arg
	variant. Honour "initialize" flag.
	* java/lang/Class.java: Fix forName() declaration.
	* java/lang/ClassLoader.java (getParent): Now final.
	(findSystemClass): Now final.
	(getSystemResourceAsStream): Remove redundant "final" modifier.
	(getSystemResource): Remove redundant "final" modifier.
	(getResources): Now final.
	(getSystemClassLoader): Now non-native.
	* java/util/ResourceBundle.java (tryGetSomeBundle): Use the correct
	arguments for Class.forName().
	* gnu/gcj/runtime/VMClassLoader.java (getVMClassLoader): Removed.
	(instance): Static initialize singleton.
	(findClass): Override this, not findSystemClass.
	* java/lang/natClassLoader.cc (findClass): Renamed from 
	findSystemClass. Call the interpreter via URLClassLoader.findClass if 
	loading class via dlopen fails.


Index: java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/Class.h,v
retrieving revision 1.31
diff -u -r1.31 Class.h
--- Class.h	2001/01/17 10:22:32	1.31
+++ Class.h	2001/05/06 14:01:47
@@ -98,6 +98,13 @@
   jshort count;
 };
 
+// Used for vtable pointer manipulation.
+union _Jv_Self
+{
+  char *vtable_ptr;
+  jclass self;
+};
+
 #define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
 
 #define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
@@ -105,7 +112,8 @@
 class java::lang::Class : public java::lang::Object
 {
 public:
-  static jclass forName (jstring className, java::lang::ClassLoader *loader);
+  static jclass forName (jstring className, jboolean initialize, 
+                         java::lang::ClassLoader *loader);
   static jclass forName (jstring className);
   JArray<jclass> *getClasses (void);
 
@@ -208,9 +216,8 @@
 
     // C++ ctors set the vtbl pointer to point at an offset inside the vtable
     // object. That doesn't work for Java, so this hack adjusts it back.
-    void *p =  ((void **)this)[0];
-    ((void **)this)[0] = (void *)((char *)p-2*sizeof (void *));
-
+    ((_Jv_Self *)this)->vtable_ptr -= 2 * sizeof (void *);
+    
     // We must initialize every field of the class.  We do this in the
     // same order they are declared in Class.h, except for fields that
     // are initialized to NULL.
Index: java/lang/natClass.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/natClass.cc,v
retrieving revision 1.36.2.2
diff -u -r1.36.2.2 natClass.cc
--- natClass.cc	2001/03/24 00:27:41	1.36.2.2
+++ natClass.cc	2001/05/06 14:01:48
@@ -72,7 +72,8 @@
 
 
 jclass
-java::lang::Class::forName (jstring className, java::lang::ClassLoader *loader)
+java::lang::Class::forName (jstring className, jboolean initialize,
+                            java::lang::ClassLoader *loader)
 {
   if (! className)
     JvThrow (new java::lang::NullPointerException);
@@ -90,10 +91,11 @@
 		  ? _Jv_FindClassFromSignature (name->data, loader)
 		  : _Jv_FindClass (name, loader));
 
-  if (klass)
+  if (klass == NULL)
+    throw new java::lang::ClassNotFoundException (className);
+ 
+  if (initialize)
     _Jv_InitClass (klass);
-  else
-    JvThrow (new java::lang::ClassNotFoundException (className));
 
   return klass;
 }
@@ -102,7 +104,7 @@
 java::lang::Class::forName (jstring className)
 {
   // FIXME: should use class loader from calling method.
-  return forName (className, NULL);
+  return forName (className, true, NULL);
 }
 
 java::lang::reflect::Constructor *
Index: java/lang/Class.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/Class.java,v
retrieving revision 1.10
diff -u -r1.10 Class.java
--- Class.java	2000/11/26 03:58:55	1.10
+++ Class.java	2001/05/06 14:01:48
@@ -30,7 +30,9 @@
 {
   public static native Class forName (String className)
     throws ClassNotFoundException;
-  public static native Class forName (String className, ClassLoader loader)
+  /** @since 1.2 */
+  public static native Class forName (String className, boolean initialize,
+				      ClassLoader loader)
     throws ClassNotFoundException;
   public native Class[] getClasses ();
   public native ClassLoader getClassLoader ();
Index: java/lang/ClassLoader.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/ClassLoader.java,v
retrieving revision 1.11
diff -u -r1.11 ClassLoader.java
--- ClassLoader.java	2000/11/27 04:07:48	1.11
+++ ClassLoader.java	2001/05/06 14:01:48
@@ -1,6 +1,6 @@
 // ClassLoader.java - Define policies for loading Java classes.
 
-/* Copyright (C) 1998, 1999, 2000  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -25,18 +25,23 @@
  * @author  Kresten Krab Thorup
  */
 
-public abstract class ClassLoader {
-
+public abstract class ClassLoader
+{
   static private ClassLoader system;
   private ClassLoader parent;
 
-  public ClassLoader getParent ()
+  public final ClassLoader getParent ()
   {
     /* FIXME: security */
     return parent;
   }
-    
-  public static native ClassLoader getSystemClassLoader ();
+
+  public static ClassLoader getSystemClassLoader ()
+  {
+    if (system == null)
+      system = gnu.gcj.runtime.VMClassLoader.instance;
+    return system;
+  }
 
   /**
    * Creates a <code>ClassLoader</code> with no parent.
@@ -55,6 +60,7 @@
    * <code>checkCreateClassLoader</code> on the current 
    * security manager. 
    * @exception java.lang.SecurityException if not allowed
+   * @since 1.2
    */
   protected ClassLoader(ClassLoader parent) 
   {
@@ -71,12 +77,12 @@
    * @see       ClassLoader#loadClass(String,boolean)
    * @exception java.lang.ClassNotFoundException 
    */ 
-  public Class loadClass(String name) 
-    throws java.lang.ClassNotFoundException, java.lang.LinkageError
+  public Class loadClass(String name)
+    throws java.lang.ClassNotFoundException
   { 
     return loadClass (name, false);
   }
-
+  
   /** 
    * Loads the class by the given name.  The default implementation
    * will search for the class in the following order (similar to jdk 1.2)
@@ -96,7 +102,7 @@
    * @deprecated 
    */ 
   protected Class loadClass(String name, boolean link)
-    throws java.lang.ClassNotFoundException, java.lang.LinkageError
+    throws java.lang.ClassNotFoundException
   {
     Class c = findLoadedClass (name);
 
@@ -106,7 +112,7 @@
 	  if (parent != null)
 	    return parent.loadClass (name, link);
 	  else
-	    c = findSystemClass (name);
+	    c = system.findClass (name);
 	} catch (ClassNotFoundException ex) {
 	  /* ignore, we'll try findClass */;
 	}
@@ -130,6 +136,7 @@
    * @param name Name of the class to find.
    * @return     The class found.
    * @exception  java.lang.ClassNotFoundException
+   * @since 1.2
    */
   protected Class findClass (String name)
     throws ClassNotFoundException
@@ -201,7 +208,7 @@
       throw new java.lang.LinkageError ("class " 
 					+ name 
 					+ " already loaded");
-
+    
     try {
       // Since we're calling into native code here, 
       // we better make sure that any generated
@@ -232,7 +239,6 @@
 				     int len)
     throws ClassFormatError;
 
-
   /** 
    * Link the given class.  This will bring the class to a state where
    * the class initializer can be run.  Linking involves the following
@@ -262,13 +268,11 @@
    * @exception java.lang.LinkageError
    */
   protected final void resolveClass(Class clazz)
-    throws java.lang.LinkageError
   {
     resolveClass0(clazz);
   }
 
   static void resolveClass0(Class clazz)
-    throws java.lang.LinkageError
   {
     synchronized (clazz)
       {
@@ -288,15 +292,13 @@
 
   /** Internal method.  Calls _Jv_PrepareClass and
    * _Jv_PrepareCompiledClass.  This is only called from resolveClass.  */ 
-  private static native void linkClass0(Class clazz)
-    throws java.lang.LinkageError;
+  private static native void linkClass0(Class clazz);
 
   /** Internal method.  Marks the given clazz to be in an erroneous
    * state, and calls notifyAll() on the class object.  This should only
    * be called when the caller has the lock on the class object.  */
   private static native void markClassErrorState0(Class clazz);
 
-
   /** 
    * Returns a class found in a system-specific way, typically
    * via the <code>java.class.path</code> system property.  Loads the 
@@ -307,14 +309,14 @@
    * @exception java.lang.LinkageError 
    * @exception java.lang.ClassNotFoundException 
    */
-  protected Class findSystemClass(String name) 
-    throws java.lang.ClassNotFoundException, java.lang.LinkageError
+  protected final Class findSystemClass(String name) 
+    throws java.lang.ClassNotFoundException
   {
     return getSystemClassLoader ().loadClass (name);
   }
 
   /*
-   * Does currently nothing.
+   * Does currently nothing. FIXME.
    */ 
   protected final void setSigners(Class claz, Object[] signers) {
     /* claz.setSigners (signers); */
@@ -328,13 +330,13 @@
    * @param     name  class to find.
    * @return    the class loaded, or null.
    */ 
-  protected native Class findLoadedClass(String name);
+  protected final native Class findLoadedClass(String name);
 
-  public static final InputStream getSystemResourceAsStream(String name) {
+  public static InputStream getSystemResourceAsStream(String name) {
     return getSystemClassLoader().getResourceAsStream (name);
   }
 
-  public static final URL getSystemResource(String name) {
+  public static URL getSystemResource(String name) {
     return getSystemClassLoader().getResource (name);
   }
 
@@ -397,7 +399,7 @@
     return null;
   }
 
-  public Enumeration getResources (String name) throws IOException
+  public final Enumeration getResources (String name) throws IOException
   {
     // The rules say search the parent class if non-null,
     // otherwise search the built-in class loader (assumed to be
Index: java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.28.4.1
diff -u -r1.28.4.1 natClassLoader.cc
--- natClassLoader.cc	2001/03/03 07:28:00	1.28.4.1
+++ natClassLoader.cc	2001/05/06 14:01:48
@@ -48,15 +48,6 @@
 
 /////////// java.lang.ClassLoader native methods ////////////
 
-java::lang::ClassLoader *
-java::lang::ClassLoader::getSystemClassLoader (void)
-{
-  JvSynchronize sync (&ClassLoaderClass);
-  if (! system)
-    system = gnu::gcj::runtime::VMClassLoader::getVMClassLoader ();
-  return system;
-}
-
 java::lang::Class *
 java::lang::ClassLoader::defineClass0 (jstring name,
 				       jbyteArray data, 
@@ -178,11 +169,10 @@
   klass->notifyAll ();
 }
 
-
-/** this is the only native method in VMClassLoader, so 
-    we define it here. */
+// This is the findClass() implementation for the System classloader. It is 
+// the only native method in VMClassLoader, so we define it here.
 jclass
-gnu::gcj::runtime::VMClassLoader::findSystemClass (jstring name)
+gnu::gcj::runtime::VMClassLoader::findClass (jstring name)
 {
   _Jv_Utf8Const *name_u = _Jv_makeUtf8Const (name);
   jclass klass = _Jv_FindClassInCache (name_u, 0);
@@ -211,6 +201,12 @@
 	    klass = _Jv_FindClassInCache (name_u, 0);
 	}
     }
+    
+  // Now try loading using the interpreter.
+  if (! klass)
+    {
+      klass = java::net::URLClassLoader::findClass (name);
+    }   
 
   return klass;
 }
Index: java/io/ObjectStreamClass.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/io/ObjectStreamClass.java,v
retrieving revision 1.6.4.1
diff -u -r1.6.4.1 ObjectStreamClass.java
--- ObjectStreamClass.java	2001/03/09 01:34:40	1.6.4.1
+++ ObjectStreamClass.java	2001/05/06 14:01:48
@@ -246,13 +246,27 @@
     this.fields = fields;
   }
 
-
-  void setClass (Class clazz)
+  void setClass (Class cl) throws InvalidClassException
   {
-    this.clazz = clazz;
+    this.clazz = cl;
+    long class_uid = getClassUID (cl);
+    if (uid == 0)
+      {
+       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);
+      }
   }
 
-
   void setSuperclass (ObjectStreamClass osc)
   {
     superClass = osc;
@@ -308,7 +322,7 @@
     name = cl.getName ();
     setFlags (cl);
     setFields (cl);
-    setUID (cl);
+    uid = getClassUID (cl);
     superClass = lookup (cl.getSuperclass ());
   }
 
@@ -396,24 +410,24 @@
     calculateOffsets ();
   }
 
-  // Sets uid to be serial version UID defined by class, or if that
+  // Returns the serial version UID defined by class, or if that
   // isn't present, calculates value of serial version UID.
-  private void setUID (Class cl)
+  private long getClassUID (Class cl)
   {
     try
     {
       Field suid = cl.getDeclaredField ("serialVersionUID");
       int modifiers = suid.getModifiers ();
 
-      if (Modifier.isStatic (modifiers)
-	  && Modifier.isFinal (modifiers))
-      {
-	uid = getDefinedSUID (cl);
-	return;
-      }
+      if (Modifier.isStatic (modifiers) && Modifier.isFinal (modifiers))
+	return suid.getLong (null);	  
     }
     catch (NoSuchFieldException ignore)
-    {}
+    {
+    }
+    catch (IllegalAccessException ignore)
+    {
+    }
 
     // cl didn't define serialVersionUID, so we have to compute it
     try
@@ -534,7 +548,7 @@
       for (int i=0; i < len; i++)
 	result += (long)(sha[i] & 0xFF) << (8 * i);
 
-      uid = result;
+      return result;
     }
     catch (NoSuchAlgorithmException e)
     {
@@ -545,31 +559,6 @@
     {
       throw new RuntimeException (ioe.getMessage ());
     }
-  }
-
-
-  // Returns the value of CLAZZ's final static long field named
-  // `serialVersionUID'.
-  private long getDefinedSUID (Class clazz)
-  {
-    long l = 0;
-    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 f = clazz.getDeclaredField ("serialVersionUID");
-	l = f.getLong (null);
-      }
-    catch (java.lang.NoSuchFieldException e)
-      {
-      }
-
-    catch (java.lang.IllegalAccessException e)
-      {
-      }
-
-    return l;
   }
 
   // Returns the value of CLAZZ's private static final field named
Index: java/io/ObjectInputStream.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/io/ObjectInputStream.java,v
retrieving revision 1.6.4.1
diff -u -r1.6.4.1 ObjectInputStream.java
--- ObjectInputStream.java	2001/02/17 01:06:44	1.6.4.1
+++ ObjectInputStream.java	2001/05/06 14:01:48
@@ -199,8 +199,8 @@
 				   (class_name));
 	}
 
-	setBlockDataMode (true);
-	osc.setClass (resolveClass (osc));
+	Class cl = resolveClass (osc);
+	osc.setClass (cl);
 	setBlockDataMode (false);
 
 	if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
@@ -487,27 +487,15 @@
   protected Class resolveClass (ObjectStreamClass osc)
     throws ClassNotFoundException, IOException
   {
-//    DEBUGln ("Resolving " + osc);
-
     SecurityManager sm = System.getSecurityManager ();
-
-    if (sm == null)
-      sm = new SecurityManager () {};
 
+    // FIXME: currentClassLoader doesn't yet do anything useful. We need
+    // to call forName() with the classloader of the class which called 
+    // readObject(). See SecurityManager.getClassContext().
     ClassLoader cl = currentClassLoader (sm);
 
-    if (cl == null)
-    {
-//      DEBUGln ("No class loader found");
-      return Class.forName (osc.getName ());
-    }
-    else
-    {
-//      DEBUGln ("Using " + cl);
-      return cl.loadClass (osc.getName ());
-    }
+    return Class.forName (osc.getName (), true, cl);
   }
-
 
   /**
      Allows subclasses to resolve objects that are read from the
Index: java/io/InvalidClassException.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/io/InvalidClassException.java,v
retrieving revision 1.1
diff -u -r1.1 InvalidClassException.java
--- InvalidClassException.java	2000/05/19 17:55:31	1.1
+++ InvalidClassException.java	2001/05/06 14:01:48
@@ -44,67 +44,44 @@
   */
 public class InvalidClassException extends ObjectStreamException
 {
-
-/*
- * Instance Variables
- */
-
-/**
-  * The name of the class which encountered the error.
-  */
-public String classname;
-
-/*************************************************************************/
-
-/*
- * Constructors
- */
-
-/**
-  * Create a new InvalidClassException with a descriptive error message String
-  *
-  * @param message The descriptive error message
-  */
-public
-InvalidClassException(String message)
-{
-  super(message);
+  /**
+    * The name of the class which encountered the error.
+    */
+  public String classname;
+
+  /**
+    * Create a new InvalidClassException with a descriptive error message String
+    *
+    * @param message The descriptive error message
+    */
+  public InvalidClassException(String message)
+  {
+    super(message);
+  }
+
+  /**
+    * Create a new InvalidClassException with a descriptive error message 
+    * String, and the name of the class that caused the problem.
+    * 
+    * @param classname The number of bytes tranferred before the interruption
+    * @param message The descriptive error message
+    */
+  public InvalidClassException(String classname, String message)
+  {
+    super(message);
+    this.classname = classname;
+  }
+
+  /**
+    * Returns the descriptive error message for this exception.  It will
+    * include the class name that caused the problem if known.  This method
+    * overrides Throwable.getMessage()
+    *
+    * @return A descriptive error message
+    */
+  public String getMessage()
+  {
+    return super.getMessage() + (classname == null ? "" : ": " + classname);
+  }
 }
-
-/*************************************************************************/
-
-/**
-  * Create a new InvalidClassException with a descriptive error message 
-  * String, and the name of the class that caused the problem.
-  * 
-  * @param classname The number of bytes tranferred before the interruption
-  * @param message The descriptive error message
-  */
-public
-InvalidClassException(String classname, String message)
-{
-  super(message);
-  this.classname = classname;
-}
-
-/*************************************************************************/
-
-/*
- * Instance Methods
- */
-
-/**
-  * Returns the descriptive error message for this exception.  It will
-  * include the class name that caused the problem if known.  This method
-  * overrides Throwable.getMessage()
-  *
-  * @return A descriptive error message
-  */
-public String
-getMessage()
-{
-  return(super.getMessage() + ": " + classname);
-}
-
-} // class InvalidClassException
 
Index: java/util/ResourceBundle.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/util/ResourceBundle.java,v
retrieving revision 1.11
diff -u -r1.11 ResourceBundle.java
--- ResourceBundle.java	2000/12/15 15:49:50	1.11
+++ ResourceBundle.java	2001/05/06 14:01:48
@@ -83,9 +83,7 @@
 	{
 	  try 
 	    {
-	      // This call is wrong by the spec, but it will have to
-	      // do until our Class.forName is fixed.
-	      rbc = Class.forName(bundleName, loader);
+	      rbc = Class.forName(bundleName, true, loader);
 	      r = null;
 	      try 
 		{
Index: gnu/gcj/runtime/VMClassLoader.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/gnu/gcj/runtime/VMClassLoader.java,v
retrieving revision 1.5
diff -u -r1.5 VMClassLoader.java
--- VMClassLoader.java	2000/08/26 19:25:13	1.5
+++ VMClassLoader.java	2001/05/06 14:01:48
@@ -65,18 +65,11 @@
   /** This is overridden to search the internal hash table, which 
    * will only search existing linked-in classes.   This will make
    * the default implementation of loadClass (in ClassLoader) work right.
+   * The implementation of this method is in java/lang/natClassLoader.cc.
    */
-  protected final native Class findSystemClass(String name) 
-    throws java.lang.ClassNotFoundException, java.lang.LinkageError;
+  protected native Class findClass(String name) 
+    throws java.lang.ClassNotFoundException;
 
-  // Return the sole VMClassLoader.
-  private static synchronized VMClassLoader getVMClassLoader ()
-  {
-    if (redirect == null)
-      redirect = new VMClassLoader ();
-    return redirect;
-  }
-
   // The only VMClassLoader that can exist.
-  private static VMClassLoader redirect;
+  public static VMClassLoader instance = new VMClassLoader ();
 }

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