From d732eca9e25d41b3f9a2e9d79990881357dcf7b4 Mon Sep 17 00:00:00 2001 From: ksrini Date: Wed, 8 Oct 2008 08:10:51 -0700 Subject: [PATCH] 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 --- src/os/linux/launcher/java.c | 15 ++++----- src/os/linux/launcher/java.h | 10 ++++++ src/os/linux/launcher/java_md.c | 20 ++++++++++++ src/os/solaris/launcher/java.c | 15 ++++----- src/os/solaris/launcher/java.h | 11 +++++++ src/os/solaris/launcher/java_md.c | 21 +++++++++++++ src/share/vm/prims/jvm.cpp | 52 ++++++++++++++++++------------- 7 files changed, 108 insertions(+), 36 deletions(-) diff --git a/src/os/linux/launcher/java.c b/src/os/linux/launcher/java.c index d538db1d0..c68bb4144 100644 --- a/src/os/linux/launcher/java.c +++ b/src/os/linux/launcher/java.c @@ -1110,7 +1110,7 @@ static jstring getPlatformEncoding(JNIEnv *env) { 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 jstring getPlatformEncoding(JNIEnv *env) { 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 @@ NewPlatformString(JNIEnv *env, char *s) #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 @@ NewPlatformString(JNIEnv *env, char *s) 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 @@ NewPlatformStringArray(JNIEnv *env, char **strv, int strc) 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 @@ LoadClass(JNIEnv *env, char *name) 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 @@ GetMainClassName(JNIEnv *env, char *jarname) 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 @@ PrintJavaVersion(JNIEnv *env) 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 --git a/src/os/linux/launcher/java.h b/src/os/linux/launcher/java.h index c6f43df9c..9e4a1a6f6 100644 --- a/src/os/linux/launcher/java.h +++ b/src/os/linux/launcher/java.h @@ -100,5 +100,15 @@ void* MemAlloc(size_t size); * 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 --git a/src/os/linux/launcher/java_md.c b/src/os/linux/launcher/java_md.c index 90c6e62c3..248df18fc 100644 --- a/src/os/linux/launcher/java_md.c +++ b/src/os/linux/launcher/java_md.c @@ -1826,3 +1826,23 @@ UnsetEnv(char *name) { 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 --git a/src/os/solaris/launcher/java.c b/src/os/solaris/launcher/java.c index cb67cc0f0..17a939bb3 100644 --- a/src/os/solaris/launcher/java.c +++ b/src/os/solaris/launcher/java.c @@ -1110,7 +1110,7 @@ static jstring getPlatformEncoding(JNIEnv *env) { 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 jstring getPlatformEncoding(JNIEnv *env) { 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 @@ NewPlatformString(JNIEnv *env, char *s) #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 @@ NewPlatformString(JNIEnv *env, char *s) 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 @@ NewPlatformStringArray(JNIEnv *env, char **strv, int strc) 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 @@ LoadClass(JNIEnv *env, char *name) 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 @@ GetMainClassName(JNIEnv *env, char *jarname) 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 @@ PrintJavaVersion(JNIEnv *env) 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 --git a/src/os/solaris/launcher/java.h b/src/os/solaris/launcher/java.h index 1e3321b7d..3bea15527 100644 --- a/src/os/solaris/launcher/java.h +++ b/src/os/solaris/launcher/java.h @@ -101,4 +101,15 @@ void* MemAlloc(size_t size); */ 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 --git a/src/os/solaris/launcher/java_md.c b/src/os/solaris/launcher/java_md.c index 09f8b89ea..b006d24b6 100644 --- a/src/os/solaris/launcher/java_md.c +++ b/src/os/solaris/launcher/java_md.c @@ -1826,3 +1826,24 @@ UnsetEnv(char *name) { 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 --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp index eb99862b1..81302b712 100644 --- a/src/share/vm/prims/jvm.cpp +++ b/src/share/vm/prims/jvm.cpp @@ -628,6 +628,32 @@ JVM_ENTRY(void, JVM_ResolveClass(JNIEnv* env, jclass cls)) 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 @@ JVM_ENTRY(jclass, JVM_FindClassFromBootLoader(JNIEnv* env, 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 @@ JVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, 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 -- GitLab