7

我很难找到有关javac的代码消除功能的信息:

我读到,如果您有类似以下内容,则if- 语句将被消除:

static final boolean DEBUG = false;

if (DEBUG) System.out.println("Hello World!"); // will be removed

但是这个怎么样,例如:

static final int VALUE = 3;

if (VALUE > 9) System.out.println("VALUE > 9 ???"); // will this be removed?

或这个:

static final SomeEnum VALUE = SomeEnum.FOO;

if (VALUE==SomeEnum.BAR) System.out.println("Bar???"); // will this be removed?

由于分析程序以找到所有死代码(可能类似于停止问题)非常困难/不可能,我想只有少数定义明确的构造(如上面的第一个示例),它们javac将识别并删除可靠。是否有这些构造的完整列表?

4

4 回答 4

8

assylias 似乎找到了答案(让我把它们放在一起):

JLS 的“14.21. 无法访问的语句”一章规定,一般来说,代码中的任何无法访问的语句都被视为编译时错误,唯一的例外是对 - 语句的特殊处理if以专门允许条件编译。

因此,唯一可能导致代码消除(如果编译器选择这样做!)的构造是:

if (compileTimeConstantExpression) {
    doThis(); // may be removed if compileTimeConstantExpression == false;
} else {
    doThat(); // may be removed if compileTimeConstantExpression == true;
}

else当然,-part 是可选的)

所有其他允许代码消除的构造,例如while (false) ...,都是不允许的,而是导致编译时错误,而不是导致条件编译。

什么是可接受的定义compileTimeConstantExpression可以在JLS 的“15.28. 常量表达式”一章中找到。可以在此处找到另一个包含更多示例的精彩页面:Compile Time Constants in Java

注意:编译器不需要删除 - 语句的“无法访问”部分ifjavac似乎可以可靠地做到这一点,但其他编译器可能不会。唯一确定的方法是通过反编译检查输出,例如javap -c按照 Jon Skeet 的建议使用。

于 2013-07-31T09:42:31.633 回答
5

我已经运行了一些测试,如果条件是一个评估为假的常量表达式, javac 似乎(逻辑上)删除了代码。

总之,常量表达式是只使用常量作为操作数的表达式,即原语、字符串文字和final原语或已用常量值初始化的字符串变量。

请注意,这取决于编译器,因为 JLS 不会强制编译器像14.21底部所解释的那样聪明:

优化编译器可能会意识到语句 x=3; 永远不会被执行,并且可以选择从生成的类文件中省略该语句的代码。

于 2013-07-31T08:50:13.383 回答
0

我的猜测是这是特定于实现的(Oracle,IBM,...)。

如果您对 Oracle 的版本感兴趣,开始寻找资源的好地方是 OpenJDK 项目: http: //openjdk.java.net/groups/compiler/

于 2013-07-31T08:53:18.553 回答
0

我看到第二个例子它也被删除了

这是我的课

public class Test {

    public static void main(String[] args) throws Exception{
        final int VALUE = 3;
        if (VALUE > 9) System.out.println("VALUE > 9 ???");
    }
}

这是反编译的版本

Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[])   throws java.lang.Exception;
  Code:
   0:   return

}
于 2013-07-31T08:49:00.743 回答