如何防止调试模式代码被编译成Java中的类?

时间:2014-10-09 08:32:35

标签: java debugging

在C / C ++中,我可以使用如下

int main()
{

#if defined(DEBUG_MODE)
    // The following code may contain sensitive messages.            
    // But these sensitive messages won't be compiled into the release binary.

    A lot of debugging mode code here, which will bloat the final executable.
    ......
#endif

}

如何用Java做同样的事情?

我想要的是减少类的最终大小并删除所有敏感的调试消息。

也就是说,以下Java代码不是我想要的。

class A
{
    public void f()
    {
       if (DEBUG_MODE)
       {    // The following code may contain sensitive messages.
            // So I want to remove them before release.
            A lot of debugging mode code here, which will bloat the final executable.
            ......
        }
    }
}

4 个答案:

答案 0 :(得分:2)

你可以做的一件事是使用断言。这不会阻止代码到达您的最终Jar文件,但它将允许您告诉Java完全忽略此代码;只有在Java VM上使用-ea标志时才会执行断言。

public class Test {
    public static main(String... args) {
        assert args.length == 3;
        assert debug();


        process();
    }

    // always runs 
    public static void process() {
        // process
    }

    // only runs with -ea enabled
    public static boolean debug() {
        // debug
    }

}

因此,在调试时,确保设置-ea标志,并且运行断言,在生产代码中运行时,不要设置-ea标志,调试代码将被忽略。

这个例子是荒谬的,但重点是展示调试代码如何不影响生产代码。

答案 1 :(得分:1)

由于许多原因,这在Java中通常是不受欢迎的,但如果你真的需要完全删除,最好的办法是使用static final boolean

public static final boolean Debug = false;

public void test() {
    if ( Debug ) {
        // Debug stuff here - usually will not be included in the .class file if Debug is false.
    }
}

这通常(但据我所知,无法保证)完全删除所附的代码。

另一种方法是使用某种形式的后期绑定机制来动态加载调试类,同时为发布代码留下空存根。

答案 2 :(得分:1)

如果代码中的DEBUG_MODEstatic final boolean,则可以在“仅优化”模式下使用ProGuard。它将清除可执行文件中的所有if (false)代码。

答案 3 :(得分:0)

最终的可执行文件是压缩的,除非您有嵌入式设备或智能手机,否则很少需要担心它的大小。即使使用调试信息,您可能会发现使用压缩和更高级别的抽象,它仍然比相同的C代码小。

例如,额外的MB成本会有多大差异?我们是否在讨论需要额外的1000美元硬件?

一般来说,JIT会根据当时的状态在运行时删除代码。例如什么时候打开调试标志。