8188052: JNI FindClass needs to specify the class loading context used for library lifecycle hooks
Reviewed-by: alanb, coleenp, dholmes
--- a/src/hotspot/share/prims/jni.cpp Tue Oct 10 16:29:04 2017 +0200
+++ b/src/hotspot/share/prims/jni.cpp Tue Oct 10 11:52:42 2017 -0700
@@ -92,7 +92,7 @@
#include "jvmci/jvmciRuntime.hpp"
#endif
-static jint CurrentVersion = JNI_VERSION_9;
+static jint CurrentVersion = JNI_VERSION_10;
#ifdef _WIN32
extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* );
@@ -401,29 +401,31 @@
// Find calling class
Klass* k = thread->security_get_caller_class(0);
if (k != NULL) {
- loader = Handle(THREAD, k->class_loader());
// Special handling to make sure JNI_OnLoad and JNI_OnUnload are executed
// in the correct class context.
- if (loader.is_null() &&
+ if (k->class_loader() == NULL &&
k->name() == vmSymbols::java_lang_ClassLoader_NativeLibrary()) {
JavaValue result(T_OBJECT);
JavaCalls::call_static(&result, k,
vmSymbols::getFromClass_name(),
vmSymbols::void_class_signature(),
- thread);
- if (HAS_PENDING_EXCEPTION) {
- Handle ex(thread, thread->pending_exception());
- CLEAR_PENDING_EXCEPTION;
- THROW_HANDLE_0(ex);
- }
+ CHECK_NULL);
+ // When invoked from JNI_OnLoad, NativeLibrary::getFromClass returns
+ // a non-NULL Class object. When invoked from JNI_OnUnload,
+ // it will return NULL to indicate no context.
oop mirror = (oop) result.get_jobject();
- loader = Handle(THREAD,
- InstanceKlass::cast(java_lang_Class::as_Klass(mirror))->class_loader());
- protection_domain = Handle(THREAD,
- InstanceKlass::cast(java_lang_Class::as_Klass(mirror))->protection_domain());
+ if (mirror != NULL) {
+ Klass* fromClass = java_lang_Class::as_Klass(mirror);
+ loader = Handle(THREAD, fromClass->class_loader());
+ protection_domain = Handle(THREAD, fromClass->protection_domain());
+ }
+ } else {
+ loader = Handle(THREAD, k->class_loader());
}
- } else {
- // We call ClassLoader.getSystemClassLoader to obtain the system class loader.
+ }
+
+ if (loader.is_null()) {
+ // No context and use the system class loader
loader = Handle(THREAD, SystemDictionary::java_system_loader());
}
--- a/src/hotspot/share/prims/jni.h Tue Oct 10 16:29:04 2017 +0200
+++ b/src/hotspot/share/prims/jni.h Tue Oct 10 11:52:42 2017 -0700
@@ -1964,6 +1964,7 @@
#define JNI_VERSION_1_6 0x00010006
#define JNI_VERSION_1_8 0x00010008
#define JNI_VERSION_9 0x00090000
+#define JNI_VERSION_10 0x000a0000
#ifdef __cplusplus
} /* extern "C" */
--- a/src/hotspot/share/runtime/thread.cpp Tue Oct 10 16:29:04 2017 +0200
+++ b/src/hotspot/share/runtime/thread.cpp Tue Oct 10 11:52:42 2017 -0700
@@ -4195,6 +4195,7 @@
if (version == JNI_VERSION_1_6) return JNI_TRUE;
if (version == JNI_VERSION_1_8) return JNI_TRUE;
if (version == JNI_VERSION_9) return JNI_TRUE;
+ if (version == JNI_VERSION_10) return JNI_TRUE;
return JNI_FALSE;
}
--- a/src/java.base/share/classes/java/lang/ClassLoader.java Tue Oct 10 16:29:04 2017 +0200
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java Tue Oct 10 11:52:42 2017 -0700
@@ -2381,7 +2381,7 @@
private int jniVersion;
// the class from which the library is loaded, also indicates
// the loader this native library belongs.
- private final Class<?> fromClass;
+ private Class<?> fromClass;
// the canonicalized name of the native library.
// or static library name
String name;
@@ -2404,6 +2404,8 @@
protected void finalize() {
synchronized (loadedLibraryNames) {
if (fromClass.getClassLoader() != null && loaded) {
+ this.fromClass = null; // no context when unloaded
+
/* remove the native library name */
int size = loadedLibraryNames.size();
for (int i = 0; i < size; i++) {
--- a/src/java.base/share/native/include/jni.h Tue Oct 10 16:29:04 2017 +0200
+++ b/src/java.base/share/native/include/jni.h Tue Oct 10 11:52:42 2017 -0700
@@ -1964,6 +1964,7 @@
#define JNI_VERSION_1_6 0x00010006
#define JNI_VERSION_1_8 0x00010008
#define JNI_VERSION_9 0x00090000
+#define JNI_VERSION_10 0x000a0000
#ifdef __cplusplus
} /* extern "C" */
--- a/src/jdk.management.agent/unix/native/libmanagement_agent/FileSystemImpl.c Tue Oct 10 16:29:04 2017 +0200
+++ b/src/jdk.management.agent/unix/native/libmanagement_agent/FileSystemImpl.c Tue Oct 10 11:52:42 2017 -0700
@@ -45,7 +45,7 @@
return JNI_EVERSION; /* JNI version not supported */
}
- return JNI_VERSION_9;
+ return JNI_VERSION_10;
}
/*
--- a/src/jdk.management.agent/windows/native/libmanagement_agent/FileSystemImpl.c Tue Oct 10 16:29:04 2017 +0200
+++ b/src/jdk.management.agent/windows/native/libmanagement_agent/FileSystemImpl.c Tue Oct 10 11:52:42 2017 -0700
@@ -39,7 +39,7 @@
return JNI_EVERSION; /* JNI version not supported */
}
- return JNI_VERSION_9;
+ return JNI_VERSION_10;
}
--- a/test/hotspot/jtreg/native_sanity/JniVersion.java Tue Oct 10 16:29:04 2017 +0200
+++ b/test/hotspot/jtreg/native_sanity/JniVersion.java Tue Oct 10 11:52:42 2017 -0700
@@ -27,12 +27,12 @@
*/
public class JniVersion {
- public static final int JNI_VERSION_9 = 0x00090000;
+ public static final int JNI_VERSION_10 = 0x000a0000;
public static void main(String... args) throws Exception {
System.loadLibrary("JniVersion");
int res = getJniVersion();
- if (res != JNI_VERSION_9) {
+ if (res != JNI_VERSION_10) {
throw new Exception("Unexpected value returned from getJniVersion(): 0x" + Integer.toHexString(res));
}
}