JDK-8188069 : JNI FindClass needs to specify the class loading context used for library lifecycle hooks
  • Type: CSR
  • Component: hotspot
  • Sub-Component: runtime
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 10
  • Submitted: 2017-09-27
  • Updated: 2017-10-10
  • Resolved: 2017-10-09
Related Reports
CSR :  
Description
Summary
-------

Propose `JNI_OnLoad` to use the class loader that requests to load this native library
and `JNI_OnUnload` to use the system class loader as the class loading context
respectively.

Problem
-------

The current JNI spec does not specify the class loading context used for `JNI_OnLoad`
hooks whereas the implementation uses the class loader that requests to load the
native library as the class loading context which is very reasonable.  On the other hand,
the JNI spec specifies that `JNI_OnUnload` is called in an unknown context whereas
the implementation uses the class loader being unloaded as the context.

Solution
--------

Use the system class loader as the class loading context for `JNI_OnUnload` hook,
that is consistent with `FindClass` currently specified when there is no context.
No change in the class loading context for `JNI_OnLoad` hook but clarify it in
`JNI_OnLoad` spec. 

Specification
-------------

1) jni.h will define a new JNI version constant for JDK 10:

+#define JNI_VERSION_10  0x000a0000

(Note: the name may be revised per the decision about the version string for 
the new release cadence discussion [1])

2) The spec of `FindClass` is updated to specify the behavior when called from the
library lifecycle hooks as follows:

<pre> 
+Since JDK 10, when `FindClass` is called from a library lifecycle function
+hook the class loader is determined as follows:
+
+   * for `JNI_OnLoad` and `JNI_OnLoad_L` the class loader of the class that
+     is loading the native library is used
+   * for `JNI_OnUnload` and `JNI_OnUnload_L` the class loader returned by 
+     `ClassLoader.getSystemClassLoader` is used (as the class loader used
+      at on-load time may no longer exist) 
</pre>

3) The spec change for the `GetVersion` function:

+In JDK/JRE 10, `GetVersion()` returns `JNI_VERSION_10`.

[1] http://mail.openjdk.java.net/pipermail/discuss/2017-September/004281.html
Comments
[~alanb] The spec will be updated per your suggestion before pushing.
10-10-2017

Moving to approved.
09-10-2017

I think we should change "Since JDK 10, when `FindClass` is called from a library lifecycle function hook the class loader is determined as follows:" to "If FindClass` is called from a library lifecycle function hook, the class loader is determined as follows:" Otherwise looks good.
09-10-2017

JNI version returned by `GetVersion` function should reflect what version it supports so that the native code can implement the appropriate behavior depending on the version. For incompatible change, the version should be changed so that the native code can determine that (even fails fast if a native library only supports to run on JNI_VERSION_9 and earlier releases); otherwise, the native code would have to look at the `java.version` system property. Hence the proposed new JNI version.
04-10-2017

I don't think we have a great story with JNI version updates. Obviously the change to 1.2 and then 1.4 were significant updates with new functionality. 1.6 added one new function, as did 9, but we also bumped for 1.8 even though there does not appear to be a new API there. I believe the intent was only to update the version when new functions were added so that a library could indicate "hey I will be using functions from JNI version N so if that isn't you then don't load me". Importantly the JNI version is not used to request specific behaviour of functions - the only place a libraries requested JNI version is checked is in the classloader at library loading time. Of course, as Mandy indicates in the bug comments, a native library can query GetVersion to adapt its own behaviour in response to known JNI behaviour in a specific version. So I don't feel it essential to bump the JNI version for the current changes, but I don't see any harm either.
04-10-2017

I changed the synopsis of the bug report and CSR to "JNI_FindClass needs to specify the class loading context used for library lifecycle hooks" because the deficiency is in the JNI_FindClass specification - it fails to account for all the contexts in which it may be invoked. As per my comment in the bug report the spec for JNI_FindClass should be updated, not the spec for OnLoad or OnUnload.
29-09-2017