java – 堆栈跟踪中行号的文档

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

显示为什么我感到困惑,请采取以下代码段:

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

它给:
线程中的异常“main”java.lang.NullPointerException
at.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
at.company.training.ocjp6.App.main(App.java:30)

所以我明白,运行StringBuilder方法链接使它被视为1行(StringBuilder代码从我的编辑器的第28行开始).但是如果在evilString.toupperCase()代码片段中发生错误,那么我们将以第30行为准.

我想知道,当我看到一个堆栈跟踪,我可以知道错误发生了什么行(链接方法(多行)在我正在看的代码中很常见).

解决方法

像这样,似乎是编译器依赖于@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)

有了这个代码,我的NPE在第9行每堆栈跟踪(与源中的物理行号相匹配)

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

所以我用javap挖出一点点:

这是主要的行号表,如javap -l所示

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

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将查找行号表中最接近的先前条目,并将其放在堆栈跟踪中.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...