我很难找到有关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条答案
按热度按时间jv4diomz1#
阿西利亚斯似乎已经找到了答案(让我把它们放在一起):
JLS的“14.21.不可达语句”一章规定,一般来说,代码中任何不可达语句都被认为是编译时错误,唯一的例外是对
if
语句的特殊处理,以专门允许条件编译。因此,only构造可能导致代码消除(如果编译器选择这样做!)是:
(the
else
-当然,部件是可选的)所有其他允许代码消除的构造,例如
while (false) ...
,都是不允许的,并且会导致编译时错误,而不是导致条件编译。可接受的
compileTimeConstantExpression
的定义可以在JLS的“15.28.常量表达式”一章中找到。另一个包含更多示例的页面可以在这里找到:Compile Time Constants in Javaif
-stament的“unreachable”部分。javac
似乎可以可靠地执行此操作,但其他编译器可能做不到。唯一确定的方法是通过反编译检查输出,例如使用Jon Skeet建议的javap -c
。*dxxyhpgq2#
我已经运行了一些测试,如果条件是一个计算结果为false的常量表达式,javac似乎(逻辑上)会删除代码。
总之,常量表达式是仅使用常量作为操作数的表达式,即原语,字符串字面量和
final
原语或已用常量值初始化的Strings变量。请注意,这是编译器相关的,因为JLS并不强制编译器像14.21节最底部所解释的那样智能:
优化编译器可以认识到语句x=3;将永远不会被执行,并且可以选择从生成的类文件中省略该语句的代码。
31moq8wy3#
我看到第二个例子也被删除了
这是我的课
这是反编译版本
k5ifujac4#
我的猜测是,这是特定于实现的(Oracle,IBM,...)。
如果您对Oracle的版本感兴趣,那么开始寻找资源的好地方是OpenJDK项目:http://openjdk.java.net/groups/compiler/