-
CSR
-
Resolution: Approved
-
P3
-
None
-
behavioral
-
low
-
-
Java API
-
SE
Summary
Method::invoke
, Field::get
, Field::set
, Constructor::newInstance
APIs are specified
to perform the access check against the caller class when the API is invoked. This
CSR proposes to change the behavior if the API is invoked by JNI code with no
java frames on stack and allows access to public member of a public type that
is unconditionally exported.
Problem
Method.invoke
and Field.get
and other core reflection API to access a member
reflectively assumes there is always a caller class on the stack. It is not specified
when it is invoked by JNI code with no java frames on stack. The long-standing
behavior seems to be accidental that the implementation of a AccessibleObject
has a cache that keeps the most recent access-checked caller class. When
Field::get
is invoked early and by JNI code with null caller, the cache is null
and the access succeeded in JDK 11 as cache and caller both are null. It would
break encapsulation. JDK-8206240 introduced a regression that does not handle
null caller and resulting in NPE.
Solution
The proposed solution is to perform proper access check. When Method::invoke
,
Field::get
, Field::set
, Constructor::newInstance
are invoked by JNI code
with no java frame on stack, it allows to access to public members of a public type
in an unconditional exported API package.
If a native thread attaches to the VM and attempts to access a non-public
member or a public member in a non-exported type e.g. jdk.internal.misc.Unsafe,
it will throw IllegalAccessException
.
Specification
Update the java.lang.reflect.AccessibleObject
class specification as follows:
--- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
+++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
@@ -56,7 +56,10 @@
* {@code Field}s, {@code Method}s, or {@code Constructor}s are used to get or
* set fields, to invoke methods, or to create and initialize new instances of
* classes, respectively. Every reflected object checks that the code using it
- * is in an appropriate class, package, or module. </p>
+ * is in an appropriate class, package, or module. The check when invoked by
+ * <a href="{@docRoot}/../specs/jni/index.html">JNI code</a> with no Java
+ * class on the stack only succeeds if the member and the declaring class are
+ * public, and the class is in a package that is exported to all modules. </p>
- csr of
-
JDK-8221530 Field::get and reflective member access not handling caller = null when invoked by JNI code with no java frames on stack
-
- Resolved
-