java - javap 是否缺少一些行号?

标签 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. }

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

line 3: 0
line 6: 30
line 8: 32

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

line 3: 0
line 4: 16
line 6: 30
line 8: 32

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

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

最佳答案

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

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

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

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

static int test(int a, int b, int c, int d) {
    return
            a
           +b
           +c
           +d;
}

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

static int test(int a, int b, int c, int d) {
    return
            a
           +b
           +c+test(a,b,c,d)
           +d;
}

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

static int test(int a, int b, int c, int d) {
    return
            a
           +b+test(a,b,c,d)
           +c
           +d+test(a,b,c,d);
}

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

关于java - javap 是否缺少一些行号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34924065/

相关文章:

java - 症状及其疾病数据库设计

java - 改变注入(inject)对象的状态是不好的做法吗?

java - 在列表中查找最大和最小 double 值

java - 我如何在 [Java/Scala?] 代码中看到 Scala 编译器重写了原始 Scala 代码

java - 检测旧 Java 库的使用

jvm - Java 虚拟机规范 (JVMS) : Bug in "5.4.5 Method overriding"

java - 如何用javap查看Java代码中有哪几行字节码对应的行?

java - 为什么对父构造函数的调用不是编译器为内部类生成的构造函数中的第一个调用?

java - For循环添加新行

java - 在哪里可以找到javap应用程序的源代码?