6

我有一些 Java 代码,我想使用日志消息进行调试以进行调试。但是,最终(编译的)生产代码不应包含任何日志记录,因为它会减慢执行时间。Java中有什么方法可以在编译时禁用记录器吗?

我不害怕在运行时启用/禁用记录器的日志方法中添加的足迹检查。

if (logging==enabled) {// do logging}

但我想避免在我的生产代码中进行如下参数构造:

Logger.log("undefined state" + state + " @ " + new Date());

我正在使用 Sun 的 Java 编译器。

4

10 回答 10

6

您是否考虑过使用 {} 占位符的 slf4j 方法。这允许延迟构建 toString() 意味着如果调试日志被禁用, log.debug(...) 很便宜。

log.debug("in loop() - a={}, b={}", a, b);
于 2010-06-22T10:02:13.360 回答
2
if(logger.isDebugEnabled()) {
  logger.debug(expression);
}

我使用的每个日志框架都要求您使用上述模式以避免对日志表达式进行不必要的评估。

于 2010-06-22T09:37:02.313 回答
2

可以使用Proguard对 java 类文件进行后处理,并使用-assumenosideeffects选项删除日志记录调用。这最常用于 Android,使用:

-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
}

删除所有对等的调用Log.d(TAG, "message")...

于 2011-10-31T04:05:03.847 回答
1

没有内置的方法可以使这成为可能。您可能想要使用Java Preprocessor

于 2010-06-22T09:36:47.470 回答
1

一种方法是在 log 方法之外进行检查。与您提到的几乎相同的检查,但您自己进行:

if (LOGGER.isLoggable(Level.DEBUG)) {
    LOGGER.log("undefined state" + state + " @ " + new Date());
}

此方法可用于任何日志记录级别。有关更多信息,请参阅Logger#isLoggable(Level)。请注意,这是避免日志方法参数构造的推荐方法。

于 2010-06-22T09:37:12.997 回答
1

这似乎是您正在寻找的:

当我们打开或关闭一些日志位置时,log4j 实际上在做什么?

于 2010-06-22T09:38:30.360 回答
0

我不知道任何关于此的编译器功能,但你也可以做的是创建一个构建脚本。该脚本将复制原始(调试)Java 源文件,将它们复制到临时位置,从中剥离日志记录语句,然后编译没有调试代码的新源文件。

于 2010-06-22T09:36:42.650 回答
0

您确实应该为您的日志消息使用级别指示器,Level.SEVERE -> Level.FINEST。

Logger 中有预定义的方法,即:

Logger.info(msg);
Logger.finest(msg); // debug/trace message.

Logger.log(Level.CONFIG, "config message");

这将允许您在应用程序级别配置最小日志记录级别,并使用命令行、配置文件或手动使用 LogManager 打开/关闭低于配置级别的消息

于 2010-06-22T10:00:21.933 回答
0

我了解 Java 编译器能够消除由编译时常量表达式保护的代码块。所以理论上,你应该可以用这样的东西来做到这一点:

 public class Logging {
     public static final boolean ENABLED = true;  // change to false
 }

 public class Something
     ....

     if (Logging.ENABLED) {
          logger.debug("hello mum");
     }
 }

不幸的是,每当您更改其值时,您都需要重新编译依赖于 Logging.ENABLED 标志的每个类。所以我更喜欢以下内容:

public class Something
     ....

     if (logger.isDebugEnabled()) {
          logger.debug("hello mum");
     }
 }

它的优点是您可以在配置时甚至在运行时对日志级别进行细粒度调整;例如,使用调试器、JMX 等。此外,调用logger.isDebugEnabled()log4j 的开销非常低,除非您的代码库中有大量的日志记录,否则不太可能引起注意。

于 2010-06-22T10:37:40.170 回答
0

一个可能有效的丑陋技巧是用空实现隐藏 Logger 库的实现。优化器将内联它们,并且删除死代码应该删除参数构造。当参数构造包含副作用时,这将不起作用。

现在这是理论,我还没有在实践中测试过。不过我对此很好奇。也许这需要一个单独的问题?

于 2010-06-22T09:49:36.463 回答