JDK-8165827 : Support private interface methods in JNI, JDWP, JDI and JDB
  • Type: Enhancement
  • Component: core-svc
  • Sub-Component: debugger
  • Affected Version: 9
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-09-12
  • Updated: 2018-01-09
  • Resolved: 2016-10-19
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 9
9 b143Fixed
Related Reports
CSR :  
Relates :  
Relates :  
Relates :  
Relates :  
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.
Comments
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.
10-10-2016

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.
06-10-2016

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.
05-10-2016

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
12-09-2016