堆栈跟踪中行号的文档

时间:2012-01-02 15:17:38

标签: java stack-trace

是否有关于Java堆栈跟踪行号的明确文档?
当打印堆栈跟踪(它背后的逻辑,而不是实现)时,它们如何“计算”?

为了向您展示我为什么感到困惑,请使用以下代码段:

public static void main(String[] args) {
        String evilString = null;
        System.out.println(new StringBuilder()
                .append(evilString.toLowerCase()));
        evilString.toUpperCase();
    }

它给出: 线程“main”java.lang.NullPointerException中的异常     在be.company.training.ocjp6.App.main(App.java: 28

以下代码:

public static void main(String[] args) {
        String evilString = null;
        System.out.println(new StringBuilder()
                .append("".toLowerCase()));
        evilString.toUpperCase();
    }

给出: 线程“main”java.lang.NullPointerException中的异常     在be.company.training.ocjp6.App.main(App.java: 30

所以我理解运行StringBuilder方法链使得它被视为1行(StringBuilder代码从我编辑器的第28行开始)。但是如果在evilString.toUpperCase()片段中发生错误,我们就会回到第30行。

我想知道,当我看到一个堆栈跟踪时,我可以确定错误发生在哪一行(链接方法(在多行上)在我正在查看的代码中非常常见。)

2 个答案:

答案 0 :(得分:11)

似乎这是依赖于编译器的@kdgregory注意到的。

这是我的java -version:

java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11-402-10M3527)
Java HotSpot(TM) Client VM (build 20.4-b02-402, mixed mode)

使用此代码,我在堆栈跟踪的第9行NPE(与源中的物理行号匹配)

public static void main(String[] args) { 
    String evilString = null;
    System.out.println(new StringBuilder()
        .append(
                evilString.toLowerCase()));  // <--- NPE here (line 9)
}

所以我用javap挖了一点:

这是main的行号表,如javap -l <​​/ p>所示

(行号表显示源行:指令偏移

public static void main(java.lang.String[]);
LineNumberTable: 
line 6: 0
line 7: 2
line 9: 12
line 8: 16
line 7: 19
line 10: 22

源行9从偏移量12开始。

javap -c反汇编显示了这个:

public static void main(java.lang.String[]);
Code:
0:  aconst_null
1:  astore_1
2:  getstatic   #16; //Field java/lang/System.out:Ljava/io/PrintStream;
5:  new #22; //class java/lang/StringBuilder
8:  dup
9:  invokespecial   #24; //Method java/lang/StringBuilder."<init>":()V
12: aload_1                                                    <--- closest line in the line number table
13: invokevirtual   #25; //Method java/lang/String.toLowerCase:()Ljava/lang/String;       <--- NPE here
16: invokevirtual   #31; //Method java/lang/StringBuilder.append:      (Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual   #35; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
22: return
我估计: 当在偏移量13处的invokevirtual处命中异常时,jvm在行号表中查找最接近的先前条目并将其放入堆栈跟踪中。

答案 1 :(得分:0)

你确定Java中的""等于null吗?我相信这是你困惑的根源。你试过在第30行写"".toUpperCase();吗?

相关问题