Default methods: Possible problem with JDWP sendMethod resolution semantics

Staffan Larsen staffan.larsen at oracle.com
Tue Jan 28 02:43:01 PST 2014


This looks like a JNI omission to me. JDWP uses JNI to invoke the method, but CallNonvirtualIntMethod() does not seem to handle default methods. When called with an interface method it will always lookup the virtual implementation (just like CallIntMethod() would do).

My very naive first shot at a fix is below. It seems to work for the example program in this email thread, but I don’t know what else it breaks.

JDK-8031195 will have the same problem when we try to implement that.

Thanks,
/Staffan

--- a/src/share/vm/prims/jni.cpp
+++ b/src/share/vm/prims/jni.cpp
@@ -1320,9 +1320,14 @@
       // interface call
       KlassHandle h_holder(THREAD, holder);

+      if (call_type == JNI_VIRTUAL) {
       int itbl_index = m->itable_index();
       Klass* k = h_recv->klass();
       selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
+      } else {
+        assert(m->is_default_method(), "non virtual calls on interface methods must be on a default method");
+        selected_method = m;
+      }
     }
   }

On 28 jan 2014, at 08:35, Jaroslav Bachorik <jaroslav.bachorik at oracle.com> wrote:

> Hi,
> 
> I think this is related to https://bugs.openjdk.java.net/browse/JDK-8031195 (com.sun.jdi.InterfaceType.invokeMethod() is missing)
> 
> -JB-
> 
> On 28.1.2014 07:06, David Holmes wrote:
>> Hi Jesper,
>> 
>> This seems more of an issue with the hotspot runtime so cc'd hotspot-dev.
>> 
>> David
>> 
>> On 27/01/2014 11:37 PM, Jesper Steen Møller wrote:
>>> Hi list
>>> 
>>> I realize that this is possibly not the right list, but I'm having a
>>> lambda-related problem with the JDWP protocol (from the Eclipse Java
>>> Debugger)
>>> The problem is that I cannot invoke the default method of an interface
>>> using the equivalent of the superclass invocation syntax. Consider
>>> this example:
>>> 
>>> public interface A {
>>>    default int getOne() {
>>>        return 1;
>>>    }
>>> }
>>> 
>>> public interface B {
>>>    default int getOne() {
>>>        return 2;
>>>    }
>>> }
>>> 
>>> public class Impl implements A, B {
>>>    public int getOne() {
>>>        return B.super.getOne() + 3; // stop here and inspect
>>> B.super.getOne()
>>>    }
>>>    public static void main(String[] args) {
>>>        Impl i = new Impl();
>>>        System.out.println(i.getOne());
>>>    }
>>> }
>>> 
>>> Now, consider the line with the comment "stop here ...". Assume I have
>>> a suspended thread on that line, and I wish to inspect
>>> "B.super.getOne()", i.e. invoke the method B.getOne, using the 'this'
>>> reference as the receiver. So, I'm sending a "Invoke Method" command
>>> under the ObjectReference Command Set, like this:
>>> 
>>> object     -  objectID of 'this'
>>> thread       - threadID of suspended thread
>>> clazz         - classID of 'B'
>>> method     - methodID of 'B.getOne'
>>> arguments - 0
>>> option      - 3 (this INVOKE_SINGLE_THREADED +
>>> INVOKE_NONVIRTUALINVOKE_NONVIRTUAL)
>>> 
>>> However, the return value is '5' which indicates that the usual
>>> virtual call semantics were used on 'this'. Is this supposed to work?
>>> Have anyone tried this?
>>> 
>>> TIA,
>>> Jesper
>>> 
>>> 
> 



More information about the lambda-dev mailing list