【问题标题】:Is javap missing some line numbers?javap是否缺少一些行号?
【发布时间】:2016-04-27 17:12:19
【问题描述】:

如果我编译以下源代码:

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 行?

【问题讨论】:

  • 可能是 java-8 只是为调试添加更多消息? LineNumberTable 用于调试器将字节码与源代码连接起来。
  • 是的,用于调试器和许多其他用途,例如依赖字节码的 JaCoCo/Eclemma 等覆盖工具。实际上,Eclipse 并不使用 Javac 编译 Java 文件(而是使用内部编译器),而上述代码的字节码(即 LineNumberTable)包含所有数字(3,4,5,6,8)。
  • 您已经清楚地证明了 javac 省略了这些行号。不过,您为什么希望这些台词出现?

标签: java bytecode javap


【解决方案1】:

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

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

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

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

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新策略的猜测。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-28
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多