是否有关于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行。
我想知道,当我看到一个堆栈跟踪时,我可以确定错误发生在哪一行(链接方法(在多行上)在我正在查看的代码中非常常见。)
答案 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();
吗?