javac代码消除function

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

我读过如果你有类似下面的内容, if -statement将被删除:

 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似乎找到了答案(让我把它们放在一起):

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

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

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

(当然, else -part是可选的)

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

构成可接受的compileTimeConstantExpression的定义可以在JLS的“15.28。常量表达式”一章中找到。 可以在此处找到另一个包含更多示例的精彩页面: 在Java中编译时间常量

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

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

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

请注意,这是依赖于编译器的,因为JLS不会强制编译器如14.21最底部所解释的那样智能:

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

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

这是我的class级

 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."":()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/