无断言编译

2022-09-04 22:56:50

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

在 C 和 C++ 中,我们可以在编译时通过 before .#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);
        }
    }
}

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


答案 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

编辑

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

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


推荐