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