Java debugger can't call some default method i

2019-02-13 07:08发布

I'm coding in IntelliJ IDEA. When debugging my application, I can't use some default method implementations in Watches.

Here is a condensed example:

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");
    }
}

In main() method I put a breakpoint and set up three watches:

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

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

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

The first watch throws NoSuchMethodException complaining that method Friendship$BasicFriend.sayHiTo() doesn't exist.

The second watch runs successfully, but strangely it reports a boxed object {java.lang.Integer@537} "2" instead of just a primitive 2.

The third watch reports a primitive 1, just as expected.

Why is the first watch not working? Is this a bug? Is this actually IDE related? Is it because of some conceptual flaw of default methods? Should it be working as I want it to in the first place? Is the strange result of the second watch somehow related to the issue in the first watch?

1条回答
劫难
2楼-- · 2019-02-13 07:35

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.

查看更多
登录 后发表回答