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

Java debugger can't call some default method implementations

我正在使用 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()

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

第二个watch运行成功,但是奇怪的是报了一个boxed object {java.lang.Integer@537} "2" 而不是原始的 2.

第三个 watch 报告原始 1,正如预期的那样。

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

在 JDK 8u40 之前,JDI(Java 调试器接口)、JDWP(Java 调试器有线协议)和 JDB(标准Java 调试器)。这是 bug JDK-8042123, which is recorded as fixed in 8u40 and a corresponding blurb appears in the 8u40 release notes.

更新到 8u40 或更高版本以解决此问题,至少在 JDK 方面。

根据错误描述,似乎还需要在调试器端进行更改,以避免将 com.sun.jdi.InterfaceType 对象转换为 com.sun.jdi.ClassType,而是直接调用 InterfaceType.invokeMethod()。

在 IntelliJ 的特定情况下, that 14.1.2 has mostly fixed the issue (except the unexpected boxing), though 在该版本上有一个 ClassCastException 暗示上面的转换不正确。