在编译时禁用 Java 中的日志记录

发布于 2024-09-06 13:16:02 字数 348 浏览 6 评论 0原文

我有一些 Java 代码,我想使用日志消息来检测它们以进行调试。然而,最终(编译后的)生产代码不应包含任何日志记录,因为它会减慢执行时间。 Java 有没有办法在编译时禁用记录器?

我并不担心运行时启用/禁用记录器的日志方法内的检查会增加足迹。

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

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

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

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

I have some Java code that I'd like to instrument with log messages for debugging purposes. The final (compiled) production code, however, should not contain any logging as it would slow down the execution time. Is there any way in Java to disable a logger at compile time?

I am not afraid of the footprint a check inside the log method of a run-time enabled/disabled logger would add.

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

But I'd like to avoid parameter construction like the following in my production code:

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

I am using Sun's Java Compiler.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

甜嗑 2024-09-13 13:16:03

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

log.debug("in loop() - a={}, b={}", a, b);

Have you considered the slf4j approach with {}-placeholders. That allows for delayed construction of the toString() meaning that log.debug(...) is cheap if debug logging is disabled.

log.debug("in loop() - a={}, b={}", a, b);
瀟灑尐姊 2024-09-13 13:16:03
if(logger.isDebugEnabled()) {
  logger.debug(expression);
}

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

if(logger.isDebugEnabled()) {
  logger.debug(expression);
}

Every logging framework I've used requires you to use the above pattern to avoid unnecessary evaluation of the logging expression.

梦屿孤独相伴 2024-09-13 13:16:03

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

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

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

It is possible to post-process the java class files using Proguard and use the -assumenosideeffects option to remove the logging calls. This is done most commonly for Android using:

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

to remove all calls to Log.d(TAG, "message"), etc ...

○愚か者の日 2024-09-13 13:16:03

没有任何内置方法可以实现这一点。您可能需要使用 Java 预处理器

There is no built-in way that makes this possible. You may want to use a Java Preprocessor.

心是晴朗的。 2024-09-13 13:16:03

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

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

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

One way is to do a check outside of the log method. Almost the same check as you mentioned, but you do it yourself:

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

This method can be used with any logging level. see Logger#isLoggable(Level) for more infos.
Notice it is the recommanded way to avoid log method parameter construction.

木有鱼丸 2024-09-13 13:16:03

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

I don't know about any Compiler functionality about this, but what you also could do is create a build-script. This script would copy the original (debug) Java source files, copy them to a temporary location, strip the logging statements from them and then compile the new source files which are then without debug code.

被你宠の有点坏 2024-09-13 13:16:03

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

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

A ugly hack that might work is to hide the implementation of the Logger library with an empty implementation. The optimizer will inline them and deadcode removal should remove the parameter construction. This will not work when the parameter construction contains side-effects.

Now this is theory, I have not tested this in practice. I am curious about this though. Maybe this warrants a separate question?

心奴独伤 2024-09-13 13:16:03

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

记录器中有为此目的预定义的方法,即:

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

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

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

You really should be using a Level indicator for your log messages, Level.SEVERE -> Level.FINEST.

There are predefined methods in the Logger for this i.e:

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

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

this will allow you to configure minumim logging level at the application level and switch on/off those messages below the configured level, using the command line, configuration files or manually using the LogManager

行至春深 2024-09-13 13:16:03

据我所知,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 等。此外,在 log4j 中调用 logger.isDebugEnabled() 的开销足够低,除非您的代码库中有大量的日志记录,否则不太可能被注意到。

I understand that the Java compiler is able to eliminate blocks of code that are guarded by a compile time constant expression. So in theory, you should be able to do this with something like this:

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

 public class Something
     ....

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

Unfortunately, you need to recompile every class that depends on the Logging.ENABLED flag whenever you change its value. So I much prefer the following:

public class Something
     ....

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

which has the advantage that you can make fine-grained adjustments to the logging levels at configuration time or even at runtime; e.g. using a debugger, JMX, etc. Also, the overhead of calling logger.isDebugEnabled() in log4j is low enough that it is unlikely to be noticeable unless you have an insane amount of logging in your codebase.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文