【问题标题】:Java debugger can't call some default method implementationsJava调试器不能调用一些默认方法实现
【发布时间】:2015-05-04 17:44:08
【问题描述】:

我正在使用 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有关吗?是因为默认方法的一些概念缺陷吗?它应该首先按照我的意愿工作吗?第二只手表的奇怪结果是否与第一只手表的问题有某种关系?

【问题讨论】:

  • 重读您的问题后,除了您的第一块手表外,我得到了相同的结果。在您的第一块手表中,我收到java.lang.ClassCastException : com.sun.tools.jdi.InterfaceTypeImpl cannot be cast to com.sun.tools.jdi.ClassTypeImpl。我猜这只是一个 IntelliJ 编译器错误。我在 Ubuntu 上使用 IntelliJ 14.1.2。

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


【解决方案1】:

在 JDK 8u40 之前,JDI(Java 调试器接口)、JDWP(Java 调试器连线协议)和 JDB(标准 Java 调试器)不支持默认和静态接口方法。这是bug JDK-8042123,在8u40中记录为fixed,在8u40 release notes中出现对应的blurb。

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

从错误描述来看,调试器端似乎也需要更改,以避免将 com.sun.jdi.InterfaceType 对象转换为 com.sun.jdi.ClassType,而是直接调用 InterfaceType.invokeMethod()。

在 IntelliJ 的特定情况下,Suseika confirmed in a comment 14.1.2 已基本解决了该问题(除了意外的装箱),尽管 Mike Kobit still experiences this problem 在该版本上带有一个 ClassCastException 提示上述错误转换。

【讨论】:

  • 我安装了 Java 8u45,但仍然得到 NoSuchMethodException。但是,将 IntelliJ IDEA 从 14.0.3 更新到 14.1.2 就成功了——现在调试器中的默认方法几乎可以正常工作(第二个仍然返回装箱对象,但这是另一个问题)。
  • @Suseika 感谢您提供的信息(已编辑为答案)。这似乎证实了调试器端的更改是必需的。
  • 关于拳击。我提交了一个错误报告,你可以在这里找到它:youtrack.jetbrains.com/issue/IDEA-139945
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 1970-01-01
  • 2021-10-07
  • 1970-01-01
相关资源
最近更新 更多