javac代码消除功能

时间:2013-07-31 08:42:29

标签: java compiler-construction javac dead-code code-elimination

我很难找到有关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?

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

4 个答案:

答案 0 :(得分:7)

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

Chapter "14.21. Unreachable Statements" of the JLS指定,通常,代码中任何无法访问的语句都被视为编译时错误,唯一的例外是对if的特殊处理 - 特别允许的语句条件编译。

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

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

else - 部分当然是可选的)

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

可以在chapter "15.28. Constant Expressions" of the JLS中找到构成可接受compileTimeConstantExpression的内容的定义。可以在此处找到另一个包含更多示例的精彩页面:Compile Time Constants in Java

注意:编译器不需要删除if - stament的“无法访问”部分。 javac似乎可靠地执行此操作,但其他编译器可能不会。唯一可以确定的方法是通过反编译检查输出,例如使用Jon Skeet建议的javap -c

答案 1 :(得分:4)

我已经运行了一些测试,似乎(逻辑上)javac会删除代码,如果条件为constant expression,则计算结果为false。

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

请注意,这是编译器相关的,因为JLS不会强制编译器那么聪明,如14.21的最底部所述:

  

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

答案 2 :(得分: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

}

答案 3 :(得分:0)

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

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