JDK-8167336 : Handling of static interface methods in JDI ObjectReference.invokeMethod is incorrect and incomplete
  • Type: Bug
  • Component: core-svc
  • Sub-Component: debugger
  • Affected Version: 8u40,9
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2016-10-07
  • Updated: 2019-11-14
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 15
15Unresolved
Related Reports
Relates :  
Relates :  
Description
Changes to JDI for static and default interface methods was added under JDK-8042123. But while investigating the changes needed for private interface methods in JDK-8165827 it became apparent that the specification with respect to static interface methods was incorrect.  It 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.

The last clause prohibits nonvirtual invocation of a static interface method, but it should be allowed according to the initial spec for the method:

   /**
     * Invokes the specified {@link Method} on this object in the
     * target VM. The
     * specified method can be defined in this object's class,
     * in a superclass of this object's class, or in an interface
     * implemented by this object. The method may be a static method
     * or an instance method, but not a static initializer or constructor.

The implementation seems to support this as it delegates static method invocations to Interfacetype.invokeMethod or ClassType.invokeMethod as appropriate.

That said it is unclear why only non-virtual invocations would be affected.

On further reflection and examination of what is allowed at the Java language level I think the intent was that static interface methods can not be invoked via ObjectReference.invokeMethod, but the changes to the spec and the implementation were not consistent with that. I believe JDK-8042123 should have:

a) Changed the initial part of the invokeMethod spec from:

"The method may be a static method or an instance method, but not a static initializer or constructor."

to read something like:

"The method may be a static class method or an instance method, but not a static initializer, static interface method or constructor."

and

b) Actually implemented the logic to throw IllegalArgumentException when called for a static interface method whether virtual or non-virtual

Then the logic that dispatches to InterfaceType.invokeMethod is not needed and should be removed. 

And of course the @throws IllegalArgumentException should add "or is a static interface method" unconditionally.
Comments
Right, thanks! I've found the changeset in jdk 9: changeset: 15909:ce7f9a34492e user: dholmes date: Tue Oct 18 20:04:36 2016 -0400 summary: 8165827: Support private interface methods in JNI, JDWP, JDI and JDB
29-10-2019

Those are the changes done under JDK-8165827 which highlighted the additional issues.
29-10-2019

Ii is interesting that the jdk 8 javadoc of the JDI ObjectReference.invokeMethod() stated: Throws: 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 INVOKE_NONVIRTUAL is specified and the method is either abstract or a non-default interface member. but it was changed in the jdk 9 to say: Throws: 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 initializer, or if INVOKE_NONVIRTUAL is specified and the method is abstract. The change was: "and the method is either abstract or a non-default interface member" => "and the method is abstract" Now, does it match the previous statement? : Invokes the specified Method on this object in the target VM. The specified method can be defined in this object's class, in a superclass of this object's class, or in an interface implemented by this object. The method may be a static method or an instance method, but not a static initializer or constructor. I'm trying to find out the exact changeset with this change in jdk 9 fixes.
29-10-2019