JDK-8227491 : No documented method to specify initial caller frame from JNI
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 12.0.1,14
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: x86_64
  • Submitted: 2019-07-09
  • Updated: 2020-02-11
  • Resolved: 2019-11-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 14
14 b25Fixed
Related Reports
Relates :  
Description
A DESCRIPTION OF THE PROBLEM :
While developing a library which drives Java using the JNI I ran into issues calling methods which are marked with "jdk.internal.reflect.CallerSensitive".  Methods with this annotation call Reflection.getCallerClass.  The current implementation of Reflection.getCallerClass searches the stack frame until it finds the first stack frame which is not marked as internal.  However, when calling directly from JNI no such stack frame exists thus methods either fails or return with NullPointerException.  

There needs to be a documented method which allows JNI_CreateJavaVM to specify an object as the base caller for calls from within JNI, or some method to attach an object to a thread as the originator for this purpose.   If there is an existing interaction with thread groups and CallerSensitive/getCallerClass it is not documented.

The only work around I can find is calling a another method in Java which then calls to desired method to act as a proxy, but if this is the desired solution it is also not documented within JNI.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a JVM and call java.lang.reflect.Method.invoke using JDK 12. 

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Method is invoked
ACTUAL -
java.lang.NullPointerException
        at java.base/jdk.internal.reflect.Reflection.verifyMemberAccess(Reflection.java:130)
        at java.base/java.lang.reflect.AccessibleObject.slowVerifyAccess(AccessibleObject.java:673)
        at java.base/java.lang.reflect.AccessibleObject.verifyAccess(AccessibleObject.java:666)
        at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:638)
        at java.base/java.lang.reflect.Method.invoke(Method.java:559)


CUSTOMER SUBMITTED WORKAROUND :
No workaround exists in general for all CallerSensitive methods.  Each must be individually wrapped with Java code.

FREQUENCY : always



Comments
I've used that section to guide writing a new sub-section in the JNI Overview under "Accessing Fields and Methods" Calling Caller-Sensitive Methods A small number of Java methods have a special property called caller sensitivity. A caller-sensitive method can behave differently depending on the identity of its immediate caller. For example, an access control check may need to know the caller to determine accessibility. When native code calls such a method, there may not be any Java caller on the call-stack. It is the responsibility of the programmer to know whether the Java methods being called from their native code are caller-sensitive, and how those methods will respond if there is no Java caller. If necessary the programmer can provide Java code for the native code to call, which in turn calls the original Java method. --- I've then added links to that from the "Functions" chapter sub-sections on Calling instance/Static method: Calling Instance Methods When calling methods from native code be mindful of whether those methods may be caller-sensitive. ---
21-11-2019

Lookup class spec mentions caller-sensitive methods: https://download.java.net/java/early_access/jdk14/docs/api/java.base/java/lang/invoke/MethodHandles.Lookup.html#callsens Perhaps JNI spec can refer to it.
20-11-2019

I think the Overview -> "Accessing Fields and Methods" is a better place to mention this. Unfortunately there is no formal notion of "caller-sensitive" that I can link/reference, to give some context for this.
20-11-2019

Like Alan said, there is no problem to call StackWalker::getCallerClass if there is a Java frame on the stack. W.r.t. the JNI spec clarification about caller-sensitive methods, the overview section of chapter 5: The Invocation API seems a good place to document the warning. And "see also" links from the appropriate JNI functions.
22-07-2019

StackWalker::getCallerClass should work from JNI code, as long as there is at least one java frame on the stack. Several caller sensitive APIs don't yet specify how they behave and it will take detailed analysis and spec updates (via JDK-8177155 and maybe sub-tasks) to complete that. Mandy's suggestion to have the JNI spec include a warning about calling random methods from attached threads make sense although there may not be an obvious place to put that (AttachCurrentThread might be one place but it might also need something in the places where it describes how to call static and instance methods).
22-07-2019

> `StackWalker::getCallerClass` throws IllegalCallerException if there is no caller frame. So this API cannot be used from JNI. Thanks for the updates [~alanb] and [~mchung]. I will look at clarifying the JNI specification.
21-07-2019

Caller-sensitive methods can have different behavior depending on the caller. Each CSM should specify the behavior and handle the case when there is no Java frame on the stack (the case when the method is invoked from a JNI attached thread). `StackWalker::getCallerClass` throws IllegalCallerException if there is no caller frame. `AccessibleObject` in Java SE 13 allows a public member in a public class to be invoked when there is no caller frame if the class is in a package that is exported unconditionally. Otherwise, it isn't accessible. W.r.t. JNI specification, it may be helpful to clarify that users should pay attention to the Java caller-sensitive methods and prepare and handle the different behavior if it is invoked from a JNI attached thread, where there is no java caller frame. Moving back to the hotspot component.
19-07-2019

The AccessibleObject spec was updated via JDK-8221530 for Java SE 13 on this point. There are a number of caller sensitive methods in other areas that will also need examined, this is tracked via JDK-8177155.
19-07-2019

If there's no real solution we may just need to add documentation to the JNI specification to clarify this.
19-07-2019

Moving to core-libs->java.lang.reflect as "caller sensitivity" is primarily a libraries security concern. I'm hoping the libraries team may have some insight/suggestions on how this problem can be dealt with. Thanks.
19-07-2019

ILW = LHM = P4
11-07-2019