Java:消除死代码

时间:2011-01-21 07:38:57

标签: java compilation dead-code

我想知道Java如何处理以下场景:

假设我有一个名为Debug的类,它看起来像这样:

public class Debug 
{
    private static final boolean isAssertEnabled = true;

    public static void assertTrue(boolean b, String errorMessage) {
        if (isAssertEnabled) {
            if (!b) {
                throw new RuntimeException(errorMessage);
            }
        }
    }
}

并假设我的代码有一个看起来像这样的调用:

...
Debug.assertTrue((x + y != z) && (v - u > w), "Some error message");
....

我有几个问题:

  1. 如果 isAssertEnabled 标志设置为 false ,是否会编译出对Debug.assertTrue的整个调用?请注意,检查isAssertEnabled == true是否仅在函数调用后在函数内部进行。
  2. 如果整个调用都被编译出去,那是否也意味着编译出布尔表达式的评估?如果没有任何评价表达将是一种浪费。
  3. 谢谢你的帮助!

3 个答案:

答案 0 :(得分:6)

布尔表达式的评估不应该被编译掉 - 至少是由javac编译。

即使Debug类文件当前对值没有任何作用,谁会说在执行时会出现这种情况?

使Debug类编译后(通过使isAssertEnabled静态),javac仍然包含代码 - 但我希望JIT编译器将其删除(尽管你应该看到question Peter referenced)。是否可以将方法内联到任何内容,我不确定。同样,如果JIT编译器可以这样做,并且 if 它意识到评估参数不会产生任何副作用,它可能会避免评估。不过,我不会亲自编写代码。

答案 1 :(得分:2)

为什么要尝试构建Java本身提供的内容?

The assert keyword完全符合您的要求:可以打开和关闭它(在每个包级别上)执行,并且在禁用断言时避免对布尔表达式求值。

答案 2 :(得分:1)

这让我想起了Log4j的“isTraceEnabled()”,“isDebugEnabled()”等等。必须在if语句中明确地修改日志语句,以避免不必要的日志语句评估。

if(logger.isDebugEnabled() {
        logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}

请参阅“效果”

下的here