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
--- 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