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]

Path: FYI: Fix several libgcj PRs


I'm checking this in.

This fixes PRs 12016, 17738, and 18405.

Basically this changes how we register classes.  We no longer keep
track of initiating class loaders in C++; instead, we store them
directly in the ClassLoader (this is safe as there is no way for user
code to modify the map).  _Jv_FindClassInCache is no longer used to
search both classes loaded by dlopen (or linked in) and the initiating
loaders map; only the former.  This patch also includes some code to
register Packages for classes loaded by the bootstrap loader.  In
particular, "java.lang" will always be defined as a Package (jonas
needs this).

Tested as usual: x86 FC2, plus running Eclipse.  There is a new mauve
test for the Package functionality.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	PR libgcj/12016, PR libgcj/18405, PR libgcj/17738:
	* java/lang/Package.java (getPackages): Use VMClassLoader when
	appropriate.
	(getPackage): Likewise.
	* prims.cc (_Jv_CreateJavaVM): Call
	_Jv_RegisterBootstrapPackages.
	* include/jvm.h (_Jv_RegisterBootstrapPackages): Declare.
	* java/lang/VMClassLoader.java (getPackage): Rewrote.
	(getPackages): Likewise.
	(definedPackages): New field.
	(definePackageForNative): New method.
	* java/lang/Class.h (_Jv_FindClassInCache): Updated.
	* java/lang/natVMClassLoader.cc (loadClass): Updated.
	* defineclass.cc (handleClassBegin): Use
	ClassLoader.findLoadedClass.
	* java/lang/natClassLoader.cc (_Jv_RegisterInitiatingLoader):
	Rewrote.
	(struct _Jv_LoaderInfo): Removed.
	(initiated_classes): Likewise.
	(_Jv_UnregisterClass): Don't use initiated_classes.
	(_Jv_FindClassInCache): Likewise.  Removed 'loader' argument.
	(_Jv_FindClass): Register classes found during boostrap.
	(BOOTSTRAP_CLASS_LIST_SIZE): New define.
	(bootstrap_class_list): New global.
	(bootstrap_index): Likewise.
	(_Jv_RegisterBootstrapPackages): New function.
	* gnu/gcj/runtime/natVMClassLoader.cc (findClass): Call
	definePackageForNative.
	(findClass): Updated.
	* gnu/gcj/runtime/VMClassLoader.java (definePackageForNative):
	New method.

Index: defineclass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/defineclass.cc,v
retrieving revision 1.42
diff -u -r1.42 defineclass.cc
--- defineclass.cc 25 Nov 2004 03:46:56 -0000 1.42
+++ defineclass.cc 10 Jan 2005 19:27:14 -0000
@@ -1,6 +1,6 @@
 // defineclass.cc - defining a class from .class format.
 
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -868,7 +868,7 @@
   // was ClassLoader.defineClass called with an expected class name?
   if (def->name == 0)
     {
-      jclass orig = _Jv_FindClassInCache (loadedName, def->loader);
+      jclass orig = def->loader->findLoadedClass(loadedName->toString());
 
       if (orig == 0)
 	{
Index: prims.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/prims.cc,v
retrieving revision 1.100
diff -u -r1.100 prims.cc
--- prims.cc 25 Nov 2004 03:46:56 -0000 1.100
+++ prims.cc 10 Jan 2005 19:27:14 -0000
@@ -1,6 +1,6 @@
 // prims.cc - Code for core of runtime environment.
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -968,6 +968,8 @@
   // system loader, by having it read the class path.
   gnu::gcj::runtime::VMClassLoader::initialize();
 
+  _Jv_RegisterBootstrapPackages();
+
   no_memory = new java::lang::OutOfMemoryError;
 
   java::lang::VMThrowable::trace_enabled = 1;
Index: gnu/gcj/runtime/VMClassLoader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/VMClassLoader.java,v
retrieving revision 1.16
diff -u -r1.16 VMClassLoader.java
--- gnu/gcj/runtime/VMClassLoader.java 25 Nov 2004 03:46:59 -0000 1.16
+++ gnu/gcj/runtime/VMClassLoader.java 10 Jan 2005 19:27:14 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2001, 2002, 2003, 2004  Free Software Foundation
+/* Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -118,6 +118,27 @@
     instance.init();
   }
 
+  // Define a package for something loaded natively.
+  void definePackageForNative(String className)
+  {
+    int lastDot = className.lastIndexOf('.');
+    if (lastDot != -1)
+      {
+	String packageName = className.substring(0, lastDot);
+	if (getPackage(packageName) == null)
+	  {
+	    // FIXME: this assumes we're defining the core, which
+	    // isn't necessarily so.  We could detect this and set up
+	    // appropriately.  We could also look at a manifest file
+	    // compiled into the .so.
+	    definePackage(packageName, "Java Platform API Specification",
+			  "GNU", "1.4", "gcj", "GNU",
+			  null, // FIXME: gcj version.
+			  null);
+	  }
+      }
+  }
+
   // This keeps track of shared libraries we've already tried to load.
   private HashSet tried_libraries = new HashSet();
 
Index: gnu/gcj/runtime/natVMClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/natVMClassLoader.cc,v
retrieving revision 1.2
diff -u -r1.2 natVMClassLoader.cc
--- gnu/gcj/runtime/natVMClassLoader.cc 20 Aug 2003 15:32:23 -0000 1.2
+++ gnu/gcj/runtime/natVMClassLoader.cc 10 Jan 2005 19:27:14 -0000
@@ -1,6 +1,6 @@
 // Native code for VMClassLoader
 
-/* Copyright (C) 2002, 2003  Free Software Foundation
+/* Copyright (C) 2002, 2003, 2005  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -24,7 +24,7 @@
 gnu::gcj::runtime::VMClassLoader::findClass (jstring name)
 {
   _Jv_Utf8Const *name_u = _Jv_makeUtf8Const (name);
-  jclass klass = _Jv_FindClassInCache (name_u, 0);
+  jclass klass = _Jv_FindClassInCache (name_u);
 
   if (! klass && lib_control != LIB_NEVER)
     {
@@ -65,12 +65,14 @@
 	    so_base_name = so_base_name->substring (0, nd);
 
 	  if (loaded)
-	    klass = _Jv_FindClassInCache (name_u, 0);
+	    klass = _Jv_FindClassInCache (name_u);
 	}
     }
 
-  // Now try loading using the interpreter.
-  if (! klass)
+  // Either define the package, or try loading using the interpreter.
+  if (klass)
+    definePackageForNative(name);
+  else
     klass = java::net::URLClassLoader::findClass (name);
 
   return klass;
Index: include/jvm.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/jvm.h,v
retrieving revision 1.72
diff -u -r1.72 jvm.h
--- include/jvm.h 10 Jan 2005 19:21:46 -0000 1.72
+++ include/jvm.h 10 Jan 2005 19:27:15 -0000
@@ -561,4 +561,6 @@
 /* FIXME: this should really be defined in some more generic place */
 #define ROUND(V, A) (((((unsigned) (V))-1) | ((A)-1))+1)
 
+extern void _Jv_RegisterBootstrapPackages ();
+
 #endif /* __JAVA_JVM_H__ */
Index: java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Class.h,v
retrieving revision 1.74
diff -u -r1.74 Class.h
--- java/lang/Class.h 26 Nov 2004 02:27:54 -0000 1.74
+++ java/lang/Class.h 10 Jan 2005 19:27:15 -0000
@@ -1,6 +1,6 @@
 // Class.h - Header file for java.lang.Class.  -*- c++ -*-
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -215,8 +215,7 @@
 void _Jv_UnregisterClass (jclass);
 jclass _Jv_FindClass (_Jv_Utf8Const *name,
 		      java::lang::ClassLoader *loader);
-jclass _Jv_FindClassInCache (_Jv_Utf8Const *name,
-			     java::lang::ClassLoader *loader);
+jclass _Jv_FindClassInCache (_Jv_Utf8Const *name);
 jclass _Jv_PopClass (void);
 void _Jv_PushClass (jclass k);
 void _Jv_NewArrayClass (jclass element,
@@ -440,8 +439,7 @@
   friend void ::_Jv_UnregisterClass (jclass);
   friend jclass (::_Jv_FindClass) (_Jv_Utf8Const *name,
 				   java::lang::ClassLoader *loader);
-  friend jclass (::_Jv_FindClassInCache) (_Jv_Utf8Const *name,
-					  java::lang::ClassLoader *loader);
+  friend jclass (::_Jv_FindClassInCache) (_Jv_Utf8Const *name);
   friend jclass (::_Jv_PopClass) (void);
   friend void ::_Jv_PushClass (jclass k);
   friend void ::_Jv_NewArrayClass (jclass element,
Index: java/lang/Package.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Package.java,v
retrieving revision 1.9
diff -u -r1.9 Package.java
--- java/lang/Package.java 18 Oct 2004 10:41:55 -0000 1.9
+++ java/lang/Package.java 10 Jan 2005 19:27:15 -0000
@@ -1,5 +1,5 @@
 /* Package.java -- information about a package
-   Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -274,7 +274,7 @@
   {
     // Get the caller's classloader
     ClassLoader cl = VMSecurityManager.currentClassLoader();
-    return cl != null ? cl.getPackage(name) : null;
+    return cl != null ? cl.getPackage(name) : VMClassLoader.getPackage(name);
   }
 
   /**
@@ -288,10 +288,7 @@
     // Get the caller's classloader
     Class c = VMSecurityManager.getClassContext()[1];
     ClassLoader cl = c.getClassLoader();
-    // Sun's implementation returns the packages loaded by the bootstrap
-    // classloader if cl is null, but right now our bootstrap classloader
-    // does not create any Packages.
-    return cl != null ? cl.getPackages() : new Package[0];
+    return cl != null ? cl.getPackages() : VMClassLoader.getPackages();
   }
 
   /**
Index: java/lang/VMClassLoader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/VMClassLoader.java,v
retrieving revision 1.11
diff -u -r1.11 VMClassLoader.java
--- java/lang/VMClassLoader.java 25 Nov 2004 03:47:04 -0000 1.11
+++ java/lang/VMClassLoader.java 10 Jan 2005 19:27:15 -0000
@@ -1,6 +1,6 @@
 /* VMClassLoader.java -- Reference implementation of native interface
    required by ClassLoader
-   Copyright (C) 1998, 2001, 2002, 2003, 2004 Free Software Foundation
+   Copyright (C) 1998, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
 
 This file is part of GNU Classpath.
 
@@ -76,6 +76,8 @@
     unknownProtectionDomain = new ProtectionDomain(null, permissions);  
   }
 
+  static final HashMap definedPackages = new HashMap();
+
   /**
    * Helper to define a class using a string of bytes. This assumes that
    * the security checks have already been performed, if necessary.
@@ -173,9 +175,9 @@
    * @param name the name to find
    * @return the named package, if it exists
    */
-  static Package getPackage(String name)
+  static synchronized Package getPackage(String name)
   {
-    return null;
+    return (Package) definedPackages.get(name);
   }
 
   /**
@@ -185,9 +187,33 @@
    *
    * @return all named packages, if any exist
    */
-  static Package[] getPackages()
+  static synchronized Package[] getPackages()
+  {
+    Package[] packages = new Package[definedPackages.size()];
+    return (Package[]) definedPackages.values().toArray(packages);
+  }
+
+  // Define a package for something loaded natively.
+  static synchronized void definePackageForNative(String className)
   {
-    return new Package[0];
+    int lastDot = className.lastIndexOf('.');
+    if (lastDot != -1)
+      {
+	String packageName = className.substring(0, lastDot);
+	if (getPackage(packageName) == null)
+	  {
+	    // FIXME: this assumes we're defining the core, which
+	    // isn't necessarily so.  We could detect this and set up
+	    // appropriately.  We could also look at a manifest file
+	    // compiled into the .so.
+	    Package p = new Package(packageName,
+				    "Java Platform API Specification",
+				    "GNU", "1.4", "gcj", "GNU",
+				    null, // FIXME: gcj version.
+				    null);
+	    definedPackages.put(packageName, p);
+	  }
+      }
   }
 
   /**
Index: java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.73
diff -u -r1.73 natClassLoader.cc
--- java/lang/natClassLoader.cc 21 Dec 2004 01:03:55 -0000 1.73
+++ java/lang/natClassLoader.cc 10 Jan 2005 19:27:16 -0000
@@ -1,6 +1,6 @@
 // natClassLoader.cc - Implementation of java.lang.ClassLoader native methods.
 
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -42,19 +42,7 @@
 #include <java/lang/StringBuffer.h>
 #include <java/io/Serializable.h>
 #include <java/lang/Cloneable.h>
-
-//
-//  A single class can have many "initiating" class loaders,
-//  and a single "defining" class loader.  The Defining
-//  class loader is what is returned from Class.getClassLoader()
-//  and is used when loading dependent classes during resolution.
-//  The set of initiating class loaders are used to ensure
-//  safety of linking, and is maintained in the hash table
-//  "initiated_classes".  A defining classloader is by definition also
-//  initiating, so we only store classes in this table if they have more
-//  than one class loader associated.
-//
-
+#include <java/util/HashMap.h>
 
 // Size of local hash table.
 #define HASH_LEN 1013
@@ -62,56 +50,37 @@
 // Hash function for Utf8Consts.
 #define HASH_UTF(Utf) ((Utf)->hash16() % HASH_LEN)
 
-struct _Jv_LoaderInfo
-{
-  _Jv_LoaderInfo          *next;
-  java::lang::Class       *klass;
-  java::lang::ClassLoader *loader;
-};
-
-static _Jv_LoaderInfo *initiated_classes[HASH_LEN];
 static jclass loaded_classes[HASH_LEN];
 
 // This is the root of a linked list of classes
 static jclass stack_head;
 
+// While bootstrapping we keep a list of classes we found, so that we
+// can register their packages.  There aren't many of these so we
+// just keep a small buffer here and abort if we overflow.
+#define BOOTSTRAP_CLASS_LIST_SIZE 20
+static jclass bootstrap_class_list[BOOTSTRAP_CLASS_LIST_SIZE];
+static int bootstrap_index;
+
 
 
 
+// This tries to find a class in our built-in cache.  This cache is
+// used only for classes which are linked in to the executable or
+// loaded via dlopen().
 jclass
-_Jv_FindClassInCache (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
+_Jv_FindClassInCache (_Jv_Utf8Const *name)
 {
   JvSynchronize sync (&java::lang::Class::class$);
   jint hash = HASH_UTF (name);
 
-  if (loader && loader == java::lang::ClassLoader::getSystemClassLoader())
-    loader = NULL;
-
-  // first, if LOADER is a defining loader, then it is also initiating
   jclass klass;
   for (klass = loaded_classes[hash]; klass; klass = klass->next)
     {
-      if (loader == klass->loader && _Jv_equalUtf8Consts (name, klass->name))
+      if (_Jv_equalUtf8Consts (name, klass->name))
 	break;
     }
 
-  // otherwise, it may be that the class in question was defined
-  // by some other loader, but that the loading was initiated by 
-  // the loader in question.
-  if (!klass)
-    {
-      _Jv_LoaderInfo *info;
-      for (info = initiated_classes[hash]; info; info = info->next)
-	{
-	  if (loader == info->loader
-	      && _Jv_equalUtf8Consts (name, info->klass->name))
-	    {
-	      klass = info->klass;
-	      break;
-	    }
-	}
-    }
-
   return klass;
 }
 
@@ -130,38 +99,15 @@
 	  break;
 	}
     }
-
-  _Jv_LoaderInfo **info = &(initiated_classes[hash]);
-  for ( ; ; info = &((*info)->next))
-    {
-      while (*info && (*info)->klass == the_class)
-	{
-	  _Jv_LoaderInfo *old = *info;
-	  *info = (*info)->next;
-	  _Jv_Free (old);
-	}
-
-      if (*info == NULL)
-	break;
-    }
 }
 
+// Register an initiating class loader for a given class.
 void
 _Jv_RegisterInitiatingLoader (jclass klass, java::lang::ClassLoader *loader)
 {
-  if (loader && loader == java::lang::ClassLoader::getSystemClassLoader())
-    loader = NULL;
-
-  // This information can't be visible to the GC.
-  _Jv_LoaderInfo *info
-    = (_Jv_LoaderInfo *) _Jv_Malloc (sizeof(_Jv_LoaderInfo));
-  jint hash = HASH_UTF(klass->name);
-
-  JvSynchronize sync (&java::lang::Class::class$);
-  info->loader = loader;
-  info->klass  = klass;
-  info->next   = initiated_classes[hash];
-  initiated_classes[hash] = info;
+  if (! loader)
+    loader = java::lang::ClassLoader::getSystemClassLoader();
+  loader->loadedClasses->put(klass->name->toString(), klass);
 }
 
 // This function is called many times during startup, before main() is
@@ -254,15 +200,21 @@
 jclass
 _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
 {
-  jclass klass = _Jv_FindClassInCache (name, loader);
+  // See if the class was already loaded by this loader.  This handles
+  // initiating loader checks, as we register classes with their
+  // initiating loaders.
+  java::lang::ClassLoader *sys
+    = java::lang::ClassLoader::getSystemClassLoader ();
+  java::lang::ClassLoader *real = loader;
+  if (! real)
+    real = sys;
+  jstring sname = name->toString();
+  // We might still be bootstrapping the VM, in which case there
+  // won't be a system class loader yet.
+  jclass klass = real ? real->findLoadedClass (sname) : NULL;
 
   if (! klass)
     {
-      jstring sname = name->toString();
-
-      java::lang::ClassLoader *sys
-	= java::lang::ClassLoader::getSystemClassLoader ();
-
       if (loader)
 	{
 	  // Load using a user-defined loader, jvmspec 5.3.2
@@ -277,7 +229,7 @@
 	  if (klass && klass->getClassLoaderInternal () != delegate)
 	    _Jv_RegisterInitiatingLoader (klass, loader);
 	}
-      else 
+      else if (sys)
 	{
 	  // Load using the bootstrap loader jvmspec 5.3.1.
 	  klass = sys->loadClass (sname, false); 
@@ -286,6 +238,15 @@
 	  if (klass)
 	    _Jv_RegisterInitiatingLoader (klass, 0);
 	}
+      else
+	{
+	  // Not even a bootstrap loader, try the built-in cache.
+	  klass = _Jv_FindClassInCache (name);
+
+	  if (bootstrap_index == BOOTSTRAP_CLASS_LIST_SIZE)
+	    abort ();
+	  bootstrap_class_list[bootstrap_index++] = klass;
+	}
     }
   else
     {
@@ -297,6 +258,13 @@
   return klass;
 }
 
+void
+_Jv_RegisterBootstrapPackages ()
+{
+  for (int i = 0; i < bootstrap_index; ++i)
+    java::lang::VMClassLoader::definePackageForNative(bootstrap_class_list[i]->getName());
+}
+
 jclass
 _Jv_NewClass (_Jv_Utf8Const *name, jclass superclass,
 	      java::lang::ClassLoader *loader)
Index: java/lang/natVMClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natVMClassLoader.cc,v
retrieving revision 1.3
diff -u -r1.3 natVMClassLoader.cc
--- java/lang/natVMClassLoader.cc 25 Nov 2004 03:47:05 -0000 1.3
+++ java/lang/natVMClassLoader.cc 10 Jan 2005 19:27:16 -0000
@@ -1,6 +1,6 @@
 // natVMClassLoader.cc - VMClassLoader native methods
 
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -130,7 +130,7 @@
 java::lang::VMClassLoader::loadClass(jstring name, jboolean resolve)
 {
   _Jv_Utf8Const *utf = _Jv_makeUtf8Const (name);
-  jclass klass = _Jv_FindClassInCache (utf, NULL);
+  jclass klass = _Jv_FindClassInCache (utf);
   if (klass)
     {
       // We never want to return a class without its supers linked.
@@ -140,6 +140,9 @@
 	_Jv_InitClass (klass);
       else
 	_Jv_Linker::wait_for_state (klass, JV_STATE_LOADING);
+
+      definePackageForNative(name);
     }
+
   return klass;
 }


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