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

发布于 2024-12-24 02:36:22 字数 1051 浏览 2 评论 0原文

有没有关于 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 行开始)。但是,如果错误发生在邪恶字符串.toUpperCase() 代码段中,我们将回到第 30 行的正轨。

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

Is there any clear documentation on Java stack trace line numbers?
How are they "calculated" when printing a stack-trace (the logic behind it, not the implementaton)?

To show you why I'm confused, take the following code snippet:

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

It gives:
Exception in thread "main" java.lang.NullPointerException
at be.company.training.ocjp6.App.main(App.java:28)

While the following piece of code:

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

Gives:
Exception in thread "main" java.lang.NullPointerException
at be.company.training.ocjp6.App.main(App.java:30)

So I understand that running the chain of StringBuilder methods makes it being treated as 1 line (the StringBuilder code starts at line 28 in my editor). But if the error happens in the evilString.toUpperCase() snippet, we're back on track with line 30.

I want to know so that when I see a stacktrace, I can know for sure on what line the error happened (chaining methods (on multiple lines) is very common in the code I'm looking at).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

可是我不能没有你 2024-12-31 02:36:22

正如 @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

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

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

Seems like this is compiler dependent as @kdgregory noted.

Here's my 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)

With this code, I NPE on line 9 per the stack trace (which matches the physical line number in the source)

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

So I dug a little deeper using javap:

This is the line number table for main as shown by javap -l

(line number table shows source line: instruction-offset

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

source line 9 starts at offset 12.

javap -c to disassemble shows this:

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

my guess:
when the exception is hit at the invokevirtual at offset 13, the jvm looks up the closest prior entry in the line number table and puts that in the stack trace.

只为一人 2024-12-31 02:36:22

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

are you sure that "" equals null in Java? I believe that this is the source of your confusion. have you tried writing "".toUpperCase(); on line 30?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文