背景

这个问题与 Why does String.valueOf(null) throw a NullPointerException?

考虑以下片段:

public class StringValueOfNull {
    public static void main(String[] args) {
        String.valueOf(null);

        // programmer intention is to invoke valueOf(Object), but instead
        // code invokes valueOf(char[]) and throws NullPointerException
    }
}

如链接问题的答案中所述,Java的方法超载将上述调用解析为String.valueOf(char[]),正确地导致NullPointerException在运行时。

在日食中编译javac 1.6.0_17,这是堆栈跟踪:

Exception in thread "main" java.lang.NullPointerException
        at java.lang.String.<init>(Unknown Source)
        at java.lang.String.valueOf(Unknown Source)
        at StringValueOfNull.main(StringValueOfNull.java:3)

请注意,上面的堆栈跟踪缺少钥匙 信息:确实不是 具有完整的签名valueOf方法!它只是说String.valueOf(Unknown Source)

在我遇到的大多数情况下,异常堆栈痕迹始终具有实际上堆栈跟踪中方法的完整签名,当然是很有帮助首先提供了立即确定问题的目的,这是堆栈跟踪(不必说构造相当昂贵的)的主要原因。

但是,在这种情况下,堆栈跟踪根本没有帮助。它在帮助程序员识别问题时惨败。

正如以前的那样,我可以看到程序员可以通过上述片段识别问题的3种方法:

  • 程序员意识到该方法已超载,并且通过解决规则,在这种情况下,“错误"过载被调用
  • 程序员使用的良好IDE使他/她可以快速查看选择了哪种方法
    • 例如,在Eclipse中,在上述表达式上悬挂鼠标迅速告诉程序员String valueOf(char[] data)确实是选择的
  • 程序员检查字节码(ugh!)

最后一个选项可能是最不可访问的,但是当然是最终的答案(程序员可能会误解超载规则,IDE可能是故障的,但是bytecodes始终(?)告诉真相有关所做的事情)。


问题

  • 为什么在这种情况下,堆栈跟踪在堆栈跟踪中实际上的签名方面如此无信息?
    • 这是由于编译器吗?运行时间?还有其他吗?
  • 在其他哪些(罕见的?)方案中,堆栈跟踪无法捕获类似的基本信息?

答案

这通常与缺少的调试信息有关。您可能正在使用JRE(不是JDK),该JRE不包含RT.JAR类的调试信息。尝试使用完整的JDK,您将在堆栈跟踪中获得适当的位置:

Exception in thread "main" java.lang.NullPointerException
    at java.lang.String.<init>(String.java:177)
    at java.lang.String.valueOf(String.java:2840)
    at StringValueOfNull.main(StringValueOfNull.java:3)

来自: stackoverflow.com