我很难找到有关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}}将可靠地识别并删除。是否有这些结构的完整列表?
答案 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/