javac代码消除功能

javac代码消除功能,java,compiler-construction,javac,dead-code,code-elimination,Java,Compiler Construction,Javac,Dead Code,Code Elimination,我很难找到有关javac的代码消除功能的信息: 我读到,如果您有如下内容,则if-语句将被删除: static final boolean DEBUG=false; if(DEBUG)System.out.println(“Hello World!”);//将被删除 但是这个呢,例如: 静态最终整数值=3; 如果(值>9)System.out.println(“值>9??);//这个会被移除吗? 或者这个: static final SomeEnum VALUE=SomeEnum.FOO;

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

我读到,如果您有如下内容,则
if
-语句将被删除:

static final boolean DEBUG=false;
if(DEBUG)System.out.println(“Hello World!”);//将被删除
但是这个呢,例如:

静态最终整数值=3;
如果(值>9)System.out.println(“值>9??);//这个会被移除吗?
或者这个:

static final SomeEnum VALUE=SomeEnum.FOO;
if(VALUE==SomeEnum.BAR)System.out.println(“BAR?”);//这个会被移除吗?

由于很难/不可能分析一个程序来找到所有的死代码(可能类似于停止问题),我可以想象只有少数定义良好的结构(如上面的第一个示例),它们
javac
将可靠地识别和删除。这些结构有一个完整的列表吗?

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

这是我的课

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

}
从“Test.java”编译而来
公共类测试扩展了java.lang.Object{
公开考试();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:返回
publicstaticvoidmain(java.lang.String[])抛出java.lang.Exception;
代码:
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

}
从“Test.java”编译而来
公共类测试扩展了java.lang.Object{
公开考试();
代码:
0:aload_0
1:invokespecial#1;//方法java/lang/Object。“:()V
4:返回
publicstaticvoidmain(java.lang.String[])抛出java.lang.Exception;
代码:
0:返回
}

我已经运行了一些测试,如果条件a的计算结果为false,javac似乎(从逻辑上)会删除代码ii

总之,常量表达式是仅将常量用作操作数的表达式,即原语、字符串文字和已用常量值初始化的
final
原语或字符串变量

请注意,这取决于编译器,因为JLS不会强制编译器变得如此智能,如下面的底部所述:

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


我已经运行了一些测试,如果条件a的计算结果为false,javac似乎(逻辑上)会删除代码ii

总之,常量表达式是仅将常量用作操作数的表达式,即原语、字符串文字和已用常量值初始化的
final
原语或字符串变量

请注意,这取决于编译器,因为JLS不会强制编译器变得如此智能,如下面的底部所述:

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


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

如果您对Oracle版本感兴趣,可以从OpenJDK项目开始寻找资源:

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

如果您对Oracle版本感兴趣,可以从OpenJDK项目开始寻找资源:

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

指定,通常情况下,代码中任何无法访问的语句都被视为编译时错误,唯一的例外是对
if
-语句进行特殊处理,以专门允许条件编译

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

if(compileTimeConstantExpression){
doThis();//如果compileTimeConstantExpression==false,则可能会被删除;
}否则{
doThat();//如果compileTimeConstantExpression==true,则可能会删除;
}
(当然,
else
-部分是可选的)

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

可在中找到构成可接受的
compileTimeConstantExpression
的定义。另一个包含更多示例的伟大页面可在此处找到:


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

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

指定,通常情况下,代码中任何无法访问的语句都被视为编译时错误,唯一的例外是对
if
-语句进行特殊处理,以专门允许条件编译

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

if(compileTimeConstantExpression){
doThis();//如果compileTimeConstantExpression==false,则可能会被删除;
}否则{
doThat();//如果compileTimeConstantExpression==true,则可能会删除;
}
(当然,
else
-部分是可选的)

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