# HG changeset patch # User ksrini # Date 1223478651 25200 # Node ID f008d3631bd14d10ab999970c1d9c8a8a0e5bdfc # Parent fad66fdcb7fcba202b18caadab26597cb6054bab 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 diff -r fad66fdcb7fc -r f008d3631bd1 src/os/linux/launcher/java.c --- a/src/os/linux/launcher/java.c Mon Oct 06 11:39:34 2008 -0700 +++ b/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, "", "([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, "", "([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, "", "(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); diff -r fad66fdcb7fc -r f008d3631bd1 src/os/linux/launcher/java.h --- a/src/os/linux/launcher/java.h Mon Oct 06 11:39:34 2008 -0700 +++ b/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_ */ diff -r fad66fdcb7fc -r f008d3631bd1 src/os/linux/launcher/java_md.c --- a/src/os/linux/launcher/java_md.c Mon Oct 06 11:39:34 2008 -0700 +++ b/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); +} + diff -r fad66fdcb7fc -r f008d3631bd1 src/os/solaris/launcher/java.c --- a/src/os/solaris/launcher/java.c Mon Oct 06 11:39:34 2008 -0700 +++ b/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, "", "([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, "", "([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, "", "(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); diff -r fad66fdcb7fc -r f008d3631bd1 src/os/solaris/launcher/java.h --- a/src/os/solaris/launcher/java.h Mon Oct 06 11:39:34 2008 -0700 +++ b/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_ */ diff -r fad66fdcb7fc -r f008d3631bd1 src/os/solaris/launcher/java_md.c --- a/src/os/solaris/launcher/java_md.c Mon Oct 06 11:39:34 2008 -0700 +++ b/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); +} + diff -r fad66fdcb7fc -r f008d3631bd1 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Mon Oct 06 11:39:34 2008 -0700 +++ b/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