javac代码消除功能



我很难找到有关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会可靠地识别和删除这些结构。是否有这些构造的全面列表?

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

第14.21。JLS的"Unreachable Statements"规定,通常情况下,代码中任何不可访问的语句都被视为编译时错误,唯一的例外是对if-语句的特殊处理,以专门允许条件编译

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

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

(当然,else部分是可选的)

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

可接受compileTimeConstantExpression的定义见第15.28章。JLS的"常量表达式"。另一个有更多例子的好页面可以在这里找到:Java 中的编译时间常量

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

我运行了一些测试,javac似乎(从逻辑上)删除了代码iif(如果且仅当)条件是一个计算结果为false的常量表达式。

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

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

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

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

这是我的

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
}

我的猜测是这是特定于实现的(Oracle、IBM…)

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

相关内容

  • 没有找到相关文章

最新更新