异常堆栈跟踪中的(未知源)

时间:2010-06-28 12:24:25

标签: java exception stack-trace

背景

  

此问题与 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

在Eclipse和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)

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

在我遇到的大多数情况下,异常堆栈跟踪始终具有实际位于堆栈跟踪中的方法的完整签名,当然,非常有用可以立即识别问题并且首先提供了堆栈跟踪(不用说构造起来相当昂贵)的主要原因。

然而,在这种情况下,堆栈跟踪根本没有帮助。它在帮助程序员识别问题方面失败了。

按原样,我可以看到程序员通过以上代码段识别问题的3种方法:

  • 程序员自己意识到该方法已经过载,并且通过解析规则,在这种情况下会调用“错误”的重载
  • 程序员使用一个好的IDE,允许他/她快速查看选择的方法
    • 例如,在Eclipse中,鼠标悬停在上面的表达式上会很快告诉程序员String valueOf(char[] data)确实是选中的那个
  • 程序员检查字节码(呃!)

最后一个选项可能是最不容易访问的,但当然是终极答案(程序员可能误解了重载规则,IDE可能有问题,但字节码总是(?)说明正在做什么)。


问题

  • 在这种情况下,为什么堆栈跟踪在实际位于堆栈跟踪中的方法的签名方面如此无法提供信息?
    • 这是由于编译器吗?运行时?还有别的吗?
  • 在其他(稀有?)场景中,堆栈跟踪无法捕获这些基本信息吗?

6 个答案:

答案 0 :(得分:97)

请注意,如果您正在使用Ant构建,并且如果在javac命令中将debug属性设置为false,则可能会发生这种情况。

例如:如果您需要在Ant构建中跟踪集 debug = true 中的正确位置,

    <javac verbose="false" srcdir="${src}" destdir="${classdir}" debug="true" includes="**/*.java">
        <classpath refid="compile.classpath" />
    </javac>

答案 1 :(得分:29)

这通常与缺少调试信息有关。您可能正在使用JRE(而不是JDK),它不包含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)

答案 2 :(得分:6)

我遇到了同样的问题,我正在使用 spring apache ant 进行持续集成。

我遇到的错误是在build.xml文件中。

内容更精确的性别变更日志是:

build.xml,错误:

    <javac srcdir="${src.home}" destdir="${work.home}/WEB-INF/classes">
        <classpath refid="compile.classpath" />
    </javac>

build.xml没有错误:

    <javac srcdir="${src.home}" destdir="${work.home}/WEB-INF/classes"  debug="true">
        <classpath refid="compile.classpath" />
    </javac>

在结构中我缺乏勇气 debug =“true”

答案 3 :(得分:3)

我在Eclipse中运行了代码,得到了以下输出,

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

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

如果包含完整源代码(来自JDK),您实际上可以调试到String.java中的第177行

答案 4 :(得分:1)

当源中没有调试(行)信息或VM被告知在类加载时抛弃该信息时,会发生这种情况。由于您有一些行号,因此不是VM设置,但类String缺少调试信息。

答案 5 :(得分:1)

在Eclipse中:首选项&gt; Java&gt;已安装的JRE。选中的条目应该在JDK中有一个路径,例如C:\ Program Files(x86)\ Java \ jdk1.7.0_55 \ jre。