The current implementation of FindClass uses the class loader associated with the native library as the context to load a class when it is invoked from both JNI_OnLoad and JNI_OnUnload.
The spec of JNI_OnUnload [1] specifies that JNI_OnUnload function is called in an unknown context (such as from a finalizer), the programmer should be conservative on using Java VM services, and refrain from arbitrary Java call-backs.
FindClass may resurrect the class loader that is being finalized but the native library has already been unloaded.
The spec of JNI FindClass [2] says the following:
FindClass locates the class loader associated with the current native method; that is, the class loader of the class that declared the native method.
:
when FindClass is called through the Invocation Interface, there is no current native method or its associated class loader. In that case, the result of ClassLoader.getSystemClassLoader is used.
There are two issues here:
1. When FindClass is called from JNI_OnUnload, the context should be unknown whereas the implementation uses the class loader being unloaded.
2. The spec of FindClass needs clarification what class loader it uses when the function is called from JNI_OnUnload.
I propose to change the spec that FindClass if called from JNI_OnUnload will behave as if there is no associated class loader when called through the Invocation Interface - i.e. use ClassLoader.getSystemClassLoader as the context class loader. The new behavior will ensure the class loader being unloaded will not be resurrected and native library should not be able to find a class that is defined by a class loader being unloaded. If an native unload hook has to access any class defined by a reachable parent class loader, it should cache the class prior to unload.
[1] https://docs.oracle.com/javase/9/docs/specs/jni/invocation.html#jni_onunload
[2] https://docs.oracle.com/javase/9/docs/specs/jni/functions.html#findclass