gpt4 book ai didi

java - 有关堆栈跟踪中行号的文档

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:55:56 29 4
gpt4 key购买 nike

是否有关于 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 行的正轨。

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

最佳答案

@kdgregory 指出,这似乎是依赖于编译器的。

这是我的 java 版本:

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 所示

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

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

关于java - 有关堆栈跟踪中行号的文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8702427/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com