编译没有断言

时间:2012-06-06 15:21:09

标签: java performance assert

我知道断言可以在运行时启用/禁用,分别用于调试和生成。但是我发现断言也增加了生成的二进制文件的大小(在下面的例子中约为100-200字节)。

在C和C ++中,我们可以在编译时通过#define NDEBUG之前#include <assert.h>来完成此操作。

Java编译器有没有办法自动执行此操作?我想将它们留在源代码中以便以后进行调试。但我也不希望生成的二进制文件大于必要的大小(我们有一个大小限制作为设计要求)。

C代码:

//#define NDEBUG
#include <assert.h>

int main(void) {
    assert(0); // +200 bytes without NDEBUG, 0 with NDEBUG
    return 0;
}

Java代码:

public class Test {
    public static void main(String[] args) {
        assert(System.nanoTime()==0); // increases binary size by about 200 bytes
    }
}

回应bn。的回答:

public class Test2 {
    public static final boolean assertions = false;

    public static void main(String[] args) {
        if(assertions) {
            assert(System.nanoTime()==0);
        }
    }
}

编辑:事实上,在我看来,这种启用/禁用是比运行时更有用的编译时功能。我的意思是,有多少最终用户会启用它们?就程序员而言,在调试过程中,他/她可能会重新编译代码。

2 个答案:

答案 0 :(得分:4)

这不可能作为内置编译步骤。但是,您可以通过在断言周围添加条件块来完成此操作。

有关详细信息,请参阅文章"Removing all Trace of Assertions from Class Files"

答案 1 :(得分:2)

我个人不会这样做,因为源代码添加了复杂性,但javac在以下两个片段中为main生成了完全相同的中间代码:

有条件断言

class C {
    public final static boolean assertions = false;

    public static void main(String[] args) {
        if(assertions) {
            assert(System.nanoTime()==0);
        }
    }
}

没有断言

class C {
    public static void main(String[] args) {
    }
}

已编译的代码

  public static void main(java.lang.String[]);
    Code:
       0: return        
    LineNumberTable:
      line 3: 0

修改

  

事实上,在我看来,这种启用/禁用更有用   编译时功能比运行时。我的意思是,有多少终端用户会   启用它们吗?

它不是支持它们的最终用户,它是客户支持,告诉最终用户启用它们。我希望默认情况下它们已启用,而非禁用。