6755845: JVM_FindClassFromBoot triggers assertions
authorksrini
Wed, 08 Oct 2008 08:10:51 -0700
changeset 1420 d116726a4ca4
parent 1419 561c0debbf22
child 1424 1b2e3dd02107
6755845: JVM_FindClassFromBoot triggers assertions Summary: Fixes assertions caused by one jvm_entry calling another, solved by refactoring code and modified gamma test. Reviewed-by: dholmes, xlu
hotspot/src/os/linux/launcher/java.c
hotspot/src/os/linux/launcher/java.h
hotspot/src/os/linux/launcher/java_md.c
hotspot/src/os/solaris/launcher/java.c
hotspot/src/os/solaris/launcher/java.h
hotspot/src/os/solaris/launcher/java_md.c
hotspot/src/share/vm/prims/jvm.cpp
--- a/hotspot/src/os/linux/launcher/java.c	Mon Oct 06 11:39:34 2008 -0700
+++ b/hotspot/src/os/linux/launcher/java.c	Wed Oct 08 08:10:51 2008 -0700
@@ -1110,7 +1110,7 @@
         if (propname) {
             jclass cls;
             jmethodID mid;
-            NULL_CHECK0 (cls = (*env)->FindClass(env, "java/lang/System"));
+            NULL_CHECK0 (cls = FindBootStrapClass(env, "java/lang/System"));
             NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
                                    env, cls,
                                    "getProperty",
@@ -1125,7 +1125,7 @@
 static jboolean isEncodingSupported(JNIEnv *env, jstring enc) {
     jclass cls;
     jmethodID mid;
-    NULL_CHECK0 (cls = (*env)->FindClass(env, "java/nio/charset/Charset"));
+    NULL_CHECK0 (cls = FindBootStrapClass(env, "java/nio/charset/Charset"));
     NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
                            env, cls,
                            "isSupported",
@@ -1161,7 +1161,7 @@
 #else
             if (isEncodingSupported(env, enc) == JNI_TRUE) {
 #endif
-                NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+                NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
                 NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
                                           "([BLjava/lang/String;)V"));
                 str = (*env)->NewObject(env, cls, mid, ary, enc);
@@ -1172,7 +1172,7 @@
                   the encoding name, in which the StringCoding class will
                   pickup the iso-8859-1 as the fallback converter for us.
                 */
-                NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+                NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
                 NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
                                           "([B)V"));
                 str = (*env)->NewObject(env, cls, mid, ary);
@@ -1195,7 +1195,7 @@
     jarray ary;
     int i;
 
-    NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+    NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
     NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0));
     for (i = 0; i < strc; i++) {
         jstring str = NewPlatformString(env, *strv++);
@@ -1224,6 +1224,7 @@
         c = *t++;
         *s++ = (c == '.') ? '/' : c;
     } while (c != '\0');
+    // use the application class loader for main-class
     cls = (*env)->FindClass(env, buf);
     free(buf);
 
@@ -1250,7 +1251,7 @@
     jobject jar, man, attr;
     jstring str, result = 0;
 
-    NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile"));
+    NULL_CHECK0(cls = FindBootStrapClass(env, "java/util/jar/JarFile"));
     NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
                                           "(Ljava/lang/String;)V"));
     NULL_CHECK0(str = NewPlatformString(env, jarname));
@@ -1471,7 +1472,7 @@
     jclass ver;
     jmethodID print;
 
-    NULL_CHECK(ver = (*env)->FindClass(env, "sun/misc/Version"));
+    NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version"));
     NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V"));
 
     (*env)->CallStaticVoidMethod(env, ver, print);
--- a/hotspot/src/os/linux/launcher/java.h	Mon Oct 06 11:39:34 2008 -0700
+++ b/hotspot/src/os/linux/launcher/java.h	Wed Oct 08 08:10:51 2008 -0700
@@ -100,5 +100,15 @@
  * Make launcher spit debug output.
  */
 extern jboolean _launcher_debug;
+/*
+ * This allows for finding classes from the VM's bootstrap class loader
+ * directly, FindClass uses the application class loader internally, this will
+ * cause unnecessary searching of the classpath for the required classes.
+ */
+typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
+                                                const char *name,
+                                                jboolean throwError));
+
+jclass FindBootStrapClass(JNIEnv *env, const char *classname);
 
 #endif /* _JAVA_H_ */
--- a/hotspot/src/os/linux/launcher/java_md.c	Mon Oct 06 11:39:34 2008 -0700
+++ b/hotspot/src/os/linux/launcher/java_md.c	Wed Oct 08 08:10:51 2008 -0700
@@ -1826,3 +1826,23 @@
 {
     return(borrowed_unsetenv(name));
 }
+/*
+ * The implementation for finding classes from the bootstrap
+ * class loader, refer to java.h
+ */
+static FindClassFromBootLoader_t *findBootClass = NULL;
+
+jclass
+FindBootStrapClass(JNIEnv *env, const char* classname)
+{
+   if (findBootClass == NULL) {
+       findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
+          "JVM_FindClassFromBootLoader");
+       if (findBootClass == NULL) {
+           fprintf(stderr, "Error: could load method JVM_FindClassFromBootLoader");
+           return NULL;
+       }
+   }
+   return findBootClass(env, classname, JNI_FALSE);
+}
+
--- a/hotspot/src/os/solaris/launcher/java.c	Mon Oct 06 11:39:34 2008 -0700
+++ b/hotspot/src/os/solaris/launcher/java.c	Wed Oct 08 08:10:51 2008 -0700
@@ -1110,7 +1110,7 @@
         if (propname) {
             jclass cls;
             jmethodID mid;
-            NULL_CHECK0 (cls = (*env)->FindClass(env, "java/lang/System"));
+            NULL_CHECK0 (cls = FindBootStrapClass(env, "java/lang/System"));
             NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
                                    env, cls,
                                    "getProperty",
@@ -1125,7 +1125,7 @@
 static jboolean isEncodingSupported(JNIEnv *env, jstring enc) {
     jclass cls;
     jmethodID mid;
-    NULL_CHECK0 (cls = (*env)->FindClass(env, "java/nio/charset/Charset"));
+    NULL_CHECK0 (cls = FindBootStrapClass(env, "java/nio/charset/Charset"));
     NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
                            env, cls,
                            "isSupported",
@@ -1161,7 +1161,7 @@
 #else
             if (isEncodingSupported(env, enc) == JNI_TRUE) {
 #endif
-                NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+                NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
                 NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
                                           "([BLjava/lang/String;)V"));
                 str = (*env)->NewObject(env, cls, mid, ary, enc);
@@ -1172,7 +1172,7 @@
                   the encoding name, in which the StringCoding class will
                   pickup the iso-8859-1 as the fallback converter for us.
                 */
-                NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+                NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
                 NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
                                           "([B)V"));
                 str = (*env)->NewObject(env, cls, mid, ary);
@@ -1195,7 +1195,7 @@
     jarray ary;
     int i;
 
-    NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
+    NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
     NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0));
     for (i = 0; i < strc; i++) {
         jstring str = NewPlatformString(env, *strv++);
@@ -1224,6 +1224,7 @@
         c = *t++;
         *s++ = (c == '.') ? '/' : c;
     } while (c != '\0');
+    // use the application class loader for the main-class
     cls = (*env)->FindClass(env, buf);
     free(buf);
 
@@ -1250,7 +1251,7 @@
     jobject jar, man, attr;
     jstring str, result = 0;
 
-    NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile"));
+    NULL_CHECK0(cls = FindBootStrapClass(env, "java/util/jar/JarFile"));
     NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
                                           "(Ljava/lang/String;)V"));
     NULL_CHECK0(str = NewPlatformString(env, jarname));
@@ -1471,7 +1472,7 @@
     jclass ver;
     jmethodID print;
 
-    NULL_CHECK(ver = (*env)->FindClass(env, "sun/misc/Version"));
+    NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version"));
     NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V"));
 
     (*env)->CallStaticVoidMethod(env, ver, print);
--- a/hotspot/src/os/solaris/launcher/java.h	Mon Oct 06 11:39:34 2008 -0700
+++ b/hotspot/src/os/solaris/launcher/java.h	Wed Oct 08 08:10:51 2008 -0700
@@ -101,4 +101,15 @@
  */
 extern jboolean _launcher_debug;
 
+/*
+ * This allows for finding classes from the VM's bootstrap class loader
+ * directly, FindClass uses the application class loader internally, this will
+ * cause unnecessary searching of the classpath for the required classes.
+ */
+typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
+                                                const char *name,
+                                                jboolean throwError));
+
+jclass FindBootStrapClass(JNIEnv *env, const char *classname);
+
 #endif /* _JAVA_H_ */
--- a/hotspot/src/os/solaris/launcher/java_md.c	Mon Oct 06 11:39:34 2008 -0700
+++ b/hotspot/src/os/solaris/launcher/java_md.c	Wed Oct 08 08:10:51 2008 -0700
@@ -1826,3 +1826,24 @@
 {
     return(borrowed_unsetenv(name));
 }
+
+/*
+ * The implementation for finding classes from the bootstrap
+ * class loader, refer to java.h
+ */
+static FindClassFromBootLoader_t *findBootClass = NULL;
+
+jclass
+FindBootStrapClass(JNIEnv *env, const char* classname)
+{
+   if (findBootClass == NULL) {
+       findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
+          "JVM_FindClassFromBootLoader");
+       if (findBootClass == NULL) {
+           fprintf(stderr, "Error: could not load method JVM_FindClassFromBootLoader");
+           return NULL;
+       }
+   }
+   return findBootClass(env, classname, JNI_FALSE);
+}
+
--- a/hotspot/src/share/vm/prims/jvm.cpp	Mon Oct 06 11:39:34 2008 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Oct 08 08:10:51 2008 -0700
@@ -628,6 +628,32 @@
   if (PrintJVMWarnings) warning("JVM_ResolveClass not implemented");
 JVM_END
 
+// Common implementation for JVM_FindClassFromBootLoader and
+// JVM_FindClassFromLoader
+static jclass jvm_find_class_from_class_loader(JNIEnv* env, const char* name,
+                                  jboolean init, jobject loader,
+                                  jboolean throwError, TRAPS) {
+  // Java libraries should ensure that name is never null...
+  if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) {
+    // It's impossible to create this class;  the name cannot fit
+    // into the constant pool.
+    if (throwError) {
+      THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
+    } else {
+      THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name);
+    }
+  }
+  symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_NULL);
+  Handle h_loader(THREAD, JNIHandles::resolve(loader));
+  jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
+                                               Handle(), throwError, THREAD);
+
+  if (TraceClassResolution && result != NULL) {
+    trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result)));
+  }
+  return result;
+}
+
 // Rationale behind JVM_FindClassFromBootLoader
 // a> JVM_FindClassFromClassLoader was never exported in the export tables.
 // b> because of (a) java.dll has a direct dependecy on the  unexported
@@ -649,8 +675,8 @@
                                               jboolean throwError))
   JVMWrapper3("JVM_FindClassFromBootLoader %s throw %s", name,
               throwError ? "error" : "exception");
-  return JVM_FindClassFromClassLoader(env, name, JNI_FALSE,
-                                      (jobject)NULL, throwError);
+  return jvm_find_class_from_class_loader(env, name, JNI_FALSE,
+                                          (jobject)NULL, throwError, THREAD);
 JVM_END
 
 JVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name,
@@ -658,26 +684,8 @@
                                                jboolean throwError))
   JVMWrapper3("JVM_FindClassFromClassLoader %s throw %s", name,
                throwError ? "error" : "exception");
-  // Java libraries should ensure that name is never null...
-  if (name == NULL || (int)strlen(name) > symbolOopDesc::max_length()) {
-    // It's impossible to create this class;  the name cannot fit
-    // into the constant pool.
-    if (throwError) {
-      THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
-    } else {
-      THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name);
-    }
-  }
-  symbolHandle h_name = oopFactory::new_symbol_handle(name, CHECK_NULL);
-  Handle h_loader(THREAD, JNIHandles::resolve(loader));
-  jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
-                                               Handle(), throwError, thread);
-
-  if (TraceClassResolution && result != NULL) {
-    trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result)));
-  }
-
-  return result;
+  return jvm_find_class_from_class_loader(env, name, init, loader,
+                                          throwError, THREAD);
 JVM_END