Java调试器无法调用某些默认方法实现

时间:2015-05-04 17:44:08

标签: debugging intellij-idea interface java-8 default-method

我在IntelliJ IDEA中编码。调试我的应用程序时,我无法在 Watches 中使用某些默认方法实现。

这是一个简洁的例子:

public class Friendship {
    interface Friend {
        default void sayHiTo(Friend friend) {
            System.out.println("Hi, " + friend.hashCode());
        }

        default int amountOfHands() {
            return 2;
        }
    }

    public static class BasicFriend implements Friend {

        int numberOfFaces() {
            return 1;
        }
    }

    public static void main(String[] args) {
        System.out.println("Put a breakpoint here");
    }
}

main()方法中,我设置了断点并设置了三个监视器:

// Default interface method with dependency
new BasicFriend().sayHiTo(new BasicFriend())

// Default interface method without dependency
new BasicFriend().amountOfHands()

// Class method
new BasicFriend().numberOfFaces()

第一只手表抛出NoSuchMethodException抱怨方法Friendship$BasicFriend.sayHiTo()不存在。

第二只手表成功运行,但奇怪的是它会报告一个盒装物体 {java.lang.Integer@537} "2"而不仅仅是原始2

第三只手表报告原始1,正如预期的那样。

为什么第一只手表不工作?这是一个错误吗?这实际上与IDE有关吗?是因为默认方法的一些概念缺陷?它应该像我想要的那样起作用吗?第二只手表的奇怪结果是否与第一只手表中的问题有关?

1 个答案:

答案 0 :(得分:7)

Prior to JDK 8u40, default and static interface methods were not supported by JDI (Java Debugger Interface), JDWP (Java Debugger Wire Protocol) and JDB (the standard Java debugger). This is bug JDK-8042123, which is recorded as fixed in 8u40 and a corresponding blurb appears in the 8u40 release notes.

Update to 8u40 or later to fix this issue, at least on the JDK side.

From the bug description, it looks like debugger-side changes are also required, to avoid casting com.sun.jdi.InterfaceType objects to com.sun.jdi.ClassType, but instead call InterfaceType.invokeMethod() directly.

In the specific case of IntelliJ, Suseika confirmed in a comment that 14.1.2 has mostly fixed the issue (except the unexpected boxing), though Mike Kobit still experiences this problem on that version with a ClassCastException suggestive of the incorrect cast above.