javap是否缺少某些行号?

问题描述 投票:5回答:1

如果我编译以下源代码:

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 bytecode javap
1个回答
4
投票

嗯,没有确切指定,编译器应包含多少提示。总是要在实用性和最终代码大小之间进行权衡。在最坏的情况下,每个单字节指令将具有几个字节长度的信息。同样,某些语言构造可能会生成分布在不同字节代码位置的指令,而其他语言则根本不会映射到字节代码指令。

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.