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/