bug in the ClassLoader

minyard@acm.org minyard@acm.org
Mon Aug 27 08:22:00 GMT 2001


Tony Knaus <awk@spinnakernet.com> writes:

> This is a multi-part message in MIME format.
> --------------E3DB19E300B644FCF5A3F2FE
> Content-Type: text/plain; charset=us-ascii
> Content-Transfer-Encoding: 7bit
> 
> 
> Hi,
> 	While trying to build Apache Tomcat I have stumbled 
> across a condition where the buckets in the hash table implementing 
> the class cache in java/lang/natClassLoader.cc become populated with 
> cycles in the linked list. This causes the jvm to intermittently 
> hang when the class loader tries to find a class in the cache which 
> hashes to a bucket that has a cycle in it. 
> 
> 	This bug occured when I built a separate shared 
> library with java security objects from the gnu classpath 
> to supply missing definitions to Tomcat I inadvertently
> had a some duplication of the class name space between the 
> two libraries. Each one of the duplicated objects causes
> a linked list pointer cycle in the class cache hash table.
> Removing the duplication fixes the class cache.
> Also the cycles only seems to occur when there is a 
> name collision between the name of an object in a shared 
> library and gcj libjava. My attempts to duplicate it using 
> arbitrarily choosen class names and libraries have failed.
> 

I believe I have seen this, and I have a patch.  This occurs if the
exact same class exists in multiple shared objects; the same class
gets put into the class table twice.

Here's a patch; it's to an older version of GCJ, but it should be easy
to apply.  If it's not already in the GCJ sources, something like this
should be.

-Corey

This patch fixes a problem where the class loader goes into an infinite
loop when the same class is registered twice.  This verifies that the
class is not already loaded and prints an error if it is.

--- libjava/java/lang/natClassLoader.cc.old	Tue Jul 17 10:49:00 2001
+++ libjava/java/lang/natClassLoader.cc	Tue Jul 17 11:17:36 2001
@@ -13,6 +13,7 @@
 #include <config.h>
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 
 #include <gcj/cni.h>
@@ -439,6 +440,25 @@
     {
       jclass klass = *classes;
       jint hash = HASH_UTF (klass->name);
+      jclass check_class = loaded_classes[hash];
+
+      // If the class is already registered, don't re-register it.
+      while (check_class != NULL)
+        {
+          if (check_class == klass)
+	    {
+	      // If you get this, it means you have the same class in two
+	      // different libraries.
+	      fprintf(stderr, "***%s: Class %s was registered twice\n",
+		      "java.lang.natClassLoader.cc",
+		      klass->name->data);
+
+	      goto class_already_registered;
+	    }
+
+	  check_class = check_class->next;
+        }
+
       klass->next = loaded_classes[hash];
       loaded_classes[hash] = klass;
 
@@ -446,6 +466,9 @@
       // it to be immediately "prepared".  
       if (klass->state == JV_STATE_NOTHING)
 	klass->state = JV_STATE_COMPILED;
+
+    class_already_registered:
+      ;
     }
 }
 



More information about the Java mailing list