javap 是否缺少一些行号?

jos*_*pos 5 java bytecode javap

如果我编译以下源代码:

1.  public class Example {
2.    public boolean foo(boolean a, boolean b, char ch) {
3.      if (a && Character.isLetter(ch)
4.            || b && Character.isDigit(ch)
5.            || !a && !b) {
6.        return true;
7.      }
8.      return false;
9.    }
10. }
Run Code Online (Sandbox Code Playgroud)

使用 Java-7(OpenJDK 或 Oracle),我得到以下 LineNumberTable:

line 3: 0
line 6: 30
line 8: 32
Run Code Online (Sandbox Code Playgroud)

但是,使用 Java 8(OpenJDK 或 Oracle)编译相同的源代码,我得到另一个 LineNumberTable:

line 3: 0
line 4: 16
line 6: 30
line 8: 32
Run Code Online (Sandbox Code Playgroud)

为什么 Java 7 返回的 LineNumberTable 不包括第 4 行和第 5 行?

为什么 Java 8 返回的 LineNumberTable 不包括第 5 行?

Hol*_*ger 4

好吧,它并没有准确指定编译器应该包含多少个提示。它\xe2\x80\x99s 始终是有用性和生成的代码大小之间的权衡。在最坏的情况下,每个单字节指令都会有几个字节长度信息。此外,某些语言结构可能生成分布在不同字节代码位置的指令,而其他语言结构根本不映射到字节代码指令。

\n\n

以前的实施策略javac很简单。与 Eclipse 不同的是,它不会为表达式生成行号信息,而只为语句生成行号信息。因此,单个语句可能跨越多个源代码行,但其整个代码仅与语句\xe2\x80\x99 的第一行相关联。

\n\n

显然,此策略已更改为在存在嵌入方法调用时对此规则进行例外处理。所以对于方法调用,会有行号信息,但对于其他表达式则没有。

\n\n

您可以通过故意添加或删除嵌套调用的多行语句来验证这一点。例如,下面的代码

\n\n
static int test(int a, int b, int c, int d) {\n    return\n            a\n           +b\n           +c\n           +d;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

将仅报告一个行号,即带有return关键字的行号。现在将代码更改为

\n\n
static int test(int a, int b, int c, int d) {\n    return\n            a\n           +b\n           +c+test(a,b,c,d)\n           +d;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

行号表将有两个条目,一个是return关键字,另一个是嵌套方法调用。您可以将调用移动到不同的行,甚至添加另一个调用,例如

\n\n
static int test(int a, int b, int c, int d) {\n    return\n            a\n           +b+test(a,b,c,d)\n           +c\n           +d+test(a,b,c,d);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

行号表将支持我对javac\xe2\x80\x99 新策略的猜测。

\n