Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8280831

AccessibleObject::setAccessible throws NPE when invoked by JNI code with no java frame on stack

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • 19
    • core-libs
    • None
    • behavioral
    • minimal
    • Hide
      If a native thread attaches to the VM and call `AccessibleObject::setAccessible` and `AccessibleObject::trySetAccessible` by JNI code with no Java frame on stack, with this change, the accessible flag of public members of an exported type can only be set. If an attempt to set the accessible flag of a non-public member or a public member in a non-exported type, `AccessibleObject::trySetAccessible` will return false and `AccessibleObject::setAccessible` will throw `IllegalAccessException`.

      The compatibility risk is minimal since the existing releases since JDK 9 throws `NullPointerException`.
      Show
      If a native thread attaches to the VM and call `AccessibleObject::setAccessible` and `AccessibleObject::trySetAccessible` by JNI code with no Java frame on stack, with this change, the accessible flag of public members of an exported type can only be set. If an attempt to set the accessible flag of a non-public member or a public member in a non-exported type, `AccessibleObject::trySetAccessible` will return false and `AccessibleObject::setAccessible` will throw `IllegalAccessException`. The compatibility risk is minimal since the existing releases since JDK 9 throws `NullPointerException`.
    • Java API
    • SE

      Summary

      Clarify the behavior of java.lang.reflect.AccessibleObject::setAccessible and trySetAccessible APIs when invoked by JNI code with no Java frames on the stack that it only allows access to public member of a public type that is unconditionally exported per the access check as described in the class specification.

      Problem

      The current implementation of AccessibleObject::setAccessible and trySetAccessible throws NPE when invoked by JNI code with no Java class on the stack. The behavior of AccessibleObject::setAccessible and trySetAccessible should be consistent with the access check.

      The class spec of AccessibleObject has been updated in Java 13 (JDK-8221618) that JNI code with no Java class on the stack can only access public members of a public type that is in a package that is exported unconditionally.

      Solution

      Fix the implementation of setAccessible and trySetAccessible to allow setting the accessible flag on public members of a public type that is exported conditionally when invoked by a native thread attaches to the VM with no caller frame. Also clarify the specification of canAccess, setAccessible and trySetAccessible w.r.t. when invoked by JNI code with no Java frame on the stack.

      Specification

      AccessibleObject::setAccessible(boolean)

            *     open module. </li>
            * </ul>
            *
      +     * <p> This method may be used by <a href="{@docRoot}/../specs/jni/index.html">JNI code</a>
      +     * with no caller class on the stack to enable access to a {@link Member member}
      +     * of {@link Member#getDeclaringClass() declaring class} {@code D} if and only if:
      +     * <ul>
      +     *     <li> The member is {@code public} and {@code D} is {@code public} in
      +     *     a package that the module containing {@code D} {@link
      +     *     Module#isExported(String,Module) exports} unconditionally. </li>
      +     * </ul>
      +     *
            * <p> This method cannot be used to enable access to private members,
            * members with default (package) access, protected instance members, or
            * protected constructors when the declaring class is in a different module

      AccessibleObject::trySetAccessible

      +     * <p> If this method is invoked by <a href="{@docRoot}/../specs/jni/index.html">JNI code</a>
      +     * with no caller class on the stack, the {@code accessible} flag can
      +     * only be set if the member and the declaring class are public, and
      +     * the class is in a package that is exported unconditionally. </p>
      +     *

      AccessibleObject::canAccess

      -     * with the variation noted in the class description. </p>
      +     * with the variation noted in the class description.
      +     * If this method is invoked by <a href="{@docRoot}/../specs/jni/index.html">JNI code</a>
      +     * with no caller class on the stack, this method returns {@code true}
      +     * if the member and the declaring class are public, and the class is in
      +     * a package that is exported unconditionally. </p>
      

            mchung Mandy Chung (Inactive)
            mchung Mandy Chung (Inactive)
            Alan Bateman
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: