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

Support private interface methods in JNI, JDWP, JDI and JDB

    Details

    • Subcomponent:
    • Resolved In Build:
      b143

      Description

      For JDK 9, JDK-8071453 adds support for private methods in interfaces. As noted there, at the VM level, private interface methods have been allowed since JDK 8. However, we also need to be able to debug these methods and as such we need to incorporate them into the JNI, JDWP, JDI and JDB specifications and API's.

      For example, at present com.sun.jdi.ObjectReference.invokeMethod is specified to throw IllegalArgumentException if the NONVIRTUAL invocation mode is specified and the method is "abstract or a non-default interface method". [Aside: the specification is actually in error as it already precludes invoking static interface methods!].

      The JNI, JDWP, and JDB specifications and APIs need to examined to see whether they permit the appropriate interactions with private interface methods.

        Issue Links

          Activity

          Hide
          dholmes David Holmes added a comment -
          FC Extension Request

          This work is needed to complete the "private interface methods" feature of JDK 9.

          All of the work outlined is still to be performed, though some of the backend work is being done through JDK-8081800.

          This is low risk as it simply opens up the specifications and implementations to accept private interface methods, which are new in JDK 9. There should be no impact on any existing functional behaviour.

          Estimated ready date: Oct 14, 2016
          Show
          dholmes David Holmes added a comment - FC Extension Request This work is needed to complete the "private interface methods" feature of JDK 9. All of the work outlined is still to be performed, though some of the backend work is being done through JDK-8081800 . This is low risk as it simply opens up the specifications and implementations to accept private interface methods, which are new in JDK 9. There should be no impact on any existing functional behaviour. Estimated ready date: Oct 14, 2016
          Hide
          dholmes David Holmes added a comment -
          JDWP: No changes needed

          The JDWP spec for ObjectReference already has:

          InvokeMethod Command (6)
          Invokes a instance method. The method must be member of the object's type or one of its superclasses, superinterfaces, or implemented interfaces. Access control is not enforced; for example, private methods can be invoked.

          ---

          So private interface methods are already covered.
          Show
          dholmes David Holmes added a comment - JDWP: No changes needed The JDWP spec for ObjectReference already has: InvokeMethod Command (6) Invokes a instance method. The method must be member of the object's type or one of its superclasses, superinterfaces, or implemented interfaces. Access control is not enforced; for example, private methods can be invoked. --- So private interface methods are already covered.
          Hide
          dholmes David Holmes added a comment - - edited
          JNI: No changes needed

          getMethodID:

          "Returns the method ID for an instance (nonstatic) method of a class or interface. The method may be defined in one of the clazz’s supertypes and inherited by clazz. The method is determined by its name and signature."

          This allows for private interface methods already, but as they are not inherited, constrains their lookup to the interface that defines them. Testing confirms this is working as expected.

          ---

          Call<type>Method Routines, Call<type>MethodA Routines, Call<type>MethodV Routines:

          "These families of operations invoke an instance (nonstatic) method on a Java object, according to the specified method ID. The methodID argument must be obtained by calling GetMethodID(). When these functions are used to call private methods and constructors, the method ID must be derived from the real class of obj, not from one of its superclasses."

          Combined with the specification for getMethodID it follows that Call<Type>Method* can not be used with private methods of any kind, unless defined in the actual class of the receiver "obj". Hence private interface methods can not be invoked using this API. However testing shows that this check of the method ID is not being performed. Code inspection confirms our JNI implementation does no validation of the method ID with respect to the class of the receiver object. See related discussion in JDK-8160984.

          ---

          CallNonvirtual<type>Method Routines, CallNonvirtual<type>MethodA Routines, CallNonvirtual<type>MethodV Routines

          "These families of operations invoke an instance (nonstatic) method on a Java object, according to the specified class and method ID. The methodID argument must be obtained by calling GetMethodID() on the class clazz.

          "The CallNonvirtual<type>Method families of routines and the Call<type>Method families of routines are different. Call<type>Method routines invoke the method based on the class or interface of the object, while CallNonvirtual<type>Method routines invoke the method based on the class, designated by the clazz parameter, from which the method ID is obtained. The method ID must be obtained from the real class of the object or from one of its supertypes."

          This specification allows for private interface methods so no update is required in that regard.
          Show
          dholmes David Holmes added a comment - - edited JNI: No changes needed getMethodID: "Returns the method ID for an instance (nonstatic) method of a class or interface. The method may be defined in one of the clazz’s supertypes and inherited by clazz. The method is determined by its name and signature." This allows for private interface methods already, but as they are not inherited, constrains their lookup to the interface that defines them. Testing confirms this is working as expected. --- Call<type>Method Routines, Call<type>MethodA Routines, Call<type>MethodV Routines: "These families of operations invoke an instance (nonstatic) method on a Java object, according to the specified method ID. The methodID argument must be obtained by calling GetMethodID(). When these functions are used to call private methods and constructors, the method ID must be derived from the real class of obj, not from one of its superclasses." Combined with the specification for getMethodID it follows that Call<Type>Method* can not be used with private methods of any kind, unless defined in the actual class of the receiver "obj". Hence private interface methods can not be invoked using this API. However testing shows that this check of the method ID is not being performed. Code inspection confirms our JNI implementation does no validation of the method ID with respect to the class of the receiver object. See related discussion in JDK-8160984 . --- CallNonvirtual<type>Method Routines, CallNonvirtual<type>MethodA Routines, CallNonvirtual<type>MethodV Routines "These families of operations invoke an instance (nonstatic) method on a Java object, according to the specified class and method ID. The methodID argument must be obtained by calling GetMethodID() on the class clazz. "The CallNonvirtual<type>Method families of routines and the Call<type>Method families of routines are different. Call<type>Method routines invoke the method based on the class or interface of the object, while CallNonvirtual<type>Method routines invoke the method based on the class, designated by the clazz parameter, from which the method ID is obtained. The method ID must be obtained from the real class of the object or from one of its supertypes." This specification allows for private interface methods so no update is required in that regard.
          Hide
          dholmes David Holmes added a comment - - edited
          JDI: Changes needed to spec and implementation

          com.sun.jdi.ObjectReference.invokeMethod currently states:

               * @throws java.lang.IllegalArgumentException if the method is not
               * a member of this object's class, if the size of the argument list
               * does not match the number of declared arguments for the method,
               * if the method is a constructor or static intializer, or
               * if {@link #INVOKE_NONVIRTUAL} is specified and the method is
               * either abstract or a non-default interface member.

          which precludes invocation of private interface methods, as they are a "non-default interface member". The fix is to simply change the last line to only cover abstract methods:

               * @throws java.lang.IllegalArgumentException if the method is not
               * a member of this object's class, if the size of the argument list
               * does not match the number of declared arguments for the method,
               * if the method is a constructor or static intializer, or
               * if {@link #INVOKE_NONVIRTUAL} is specified and the method is
               * abstract.

          The implementation of ObjectReferenceImpl.validateIfaceMethodInvocation is similarly changed from:

          /*
           * Only default methods allowed for nonvirtual invokes
           */
          if (isNonVirtual(options) && !method.isDefault()) {
              throw new IllegalArgumentException("Not a default method");
          }

          to:

          /*
           * For nonvirtual invokes, method must have a body
           */
          if (isNonVirtual(options)) {
            if (method.isAbstract()) {
               throw new IllegalArgumentException("Abstract method");
             }
          }

          which matches the same check in validateClassmethodInvocation.
          Show
          dholmes David Holmes added a comment - - edited JDI: Changes needed to spec and implementation com.sun.jdi.ObjectReference.invokeMethod currently states:      * @throws java.lang.IllegalArgumentException if the method is not      * a member of this object's class, if the size of the argument list      * does not match the number of declared arguments for the method,      * if the method is a constructor or static intializer, or      * if {@link #INVOKE_NONVIRTUAL} is specified and the method is      * either abstract or a non-default interface member. which precludes invocation of private interface methods, as they are a "non-default interface member". The fix is to simply change the last line to only cover abstract methods:      * @throws java.lang.IllegalArgumentException if the method is not      * a member of this object's class, if the size of the argument list      * does not match the number of declared arguments for the method,      * if the method is a constructor or static intializer, or      * if {@link #INVOKE_NONVIRTUAL} is specified and the method is      * abstract. The implementation of ObjectReferenceImpl.validateIfaceMethodInvocation is similarly changed from: /*  * Only default methods allowed for nonvirtual invokes  */ if (isNonVirtual(options) && !method.isDefault()) {     throw new IllegalArgumentException("Not a default method"); } to: /*  * For nonvirtual invokes, method must have a body  */ if (isNonVirtual(options)) {   if (method.isAbstract()) {      throw new IllegalArgumentException("Abstract method");    } } which matches the same check in validateClassmethodInvocation.
          Hide
          hgupdate HG Updates added a comment -
          URL: http://hg.openjdk.java.net/jdk9/hs/jdk/rev/ce7f9a34492e
          User: dholmes
          Date: 2016-10-19 01:15:14 +0000
          Show
          hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/hs/jdk/rev/ce7f9a34492e User: dholmes Date: 2016-10-19 01:15:14 +0000
          Hide
          hgupdate HG Updates added a comment -
          URL: http://hg.openjdk.java.net/jdk9/hs/hotspot/rev/aeafaf272877
          User: dholmes
          Date: 2016-10-19 01:15:16 +0000
          Show
          hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/hs/hotspot/rev/aeafaf272877 User: dholmes Date: 2016-10-19 01:15:16 +0000
          Hide
          hgupdate HG Updates added a comment -
          URL: http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/aeafaf272877
          User: lana
          Date: 2016-11-03 02:17:58 +0000
          Show
          hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/aeafaf272877 User: lana Date: 2016-11-03 02:17:58 +0000
          Hide
          hgupdate HG Updates added a comment -
          URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/ce7f9a34492e
          User: lana
          Date: 2016-11-03 02:18:06 +0000
          Show
          hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/ce7f9a34492e User: lana Date: 2016-11-03 02:18:06 +0000

            People

            • Assignee:
              dholmes David Holmes
              Reporter:
              dholmes David Holmes
            • Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Due:
                Created:
                Updated:
                Resolved: