29

当我浏览一些代码时,我注意到 logger 的用法如下,

if(logger.isDebugEnabled())   
    logger.debug("Something..");

但在某些代码中,我观察到这样。

logger.debug("Something..");

当我查看log4j的源代码时,在debug()Logger本身的方法中 if(logger.isDebugEnabled())进行了检查。那为什么我们需要这种不必要的开销if(logger.isDebugEnabled())

4

5 回答 5

53

当您传递给的字符串logger.debug(...)需要时间来评估时,这很有用,在这种情况下,如果未启用调试,您可以跳过此评估。

if(logger.isDebugEnabled()) {
    logger.debug("The meaning of life is " + calculateMeaningOfLife());
}

IMO 这使代码的可读性大大降低,因此只有在性能显着提高时才应使用它。

于 2013-07-25T06:32:00.580 回答
15

isDebugEnabled 通常用于避免不必要的字符串连接,例如此调用

logger.debug("Line number = " + n);

首先调用字符串连接,然后调用 debug(),然后 Logger 才检测到未启用调试并简单地返回。这可能会显着影响应用程序的性能。

这个问题在 SLF4J 中得到了解决,它具有这样的格式化日志记录方法

public void debug(String format, Object arg);
于 2013-07-25T06:51:51.570 回答
6

Java 必须首先解析传递给调试方法的字符串参数,然后才能调用它。

logger.debug("Something.. var1=" + variable1 + "  var2=" + variable2);

上面的代码将导致创建多个 String 对象,因为每个 + 创建另一个 String ,因此在调用该方法之前您将创建大约 5 个或更多对象。

大多数情况下不会启用调试,因此检查是否启用调试比一直解析参数更有效。

于 2013-07-25T06:51:29.477 回答
4

该声明:

if(log.isDebugEnabled()){

仅出于性能原因使用。它的使用是可选的,因为它是由内部的 log 方法调用的。

但是现在你问这个检查是否是内部进行的,那我为什么要使用它呢?这很简单:如果您记录这样简单的内容:

log.debug("ResultSet rs is retrieved from OracleTypes");

然后你不需要做任何检查。如果您使用附加运算符 (+) 编写要记录的字符串,如下所示:

log.debug("[" + System.getTimeInMillis() + "] ResultSet rs is retrieved from OracleTypes");

在这种情况下,您应该检查是否启用了日志,因为如果没有,即使没有创建日志,字符串组合也是。而且我必须提醒你,使用运算符“+”来连接字符串是非常低效的。

于 2013-07-25T06:52:42.907 回答
1

SLF4J 实现(在版本 1.7.10 上检查)isDebugEnabled()在某些方法中调用,例如:

public void debug(String format, Object... arguments) {
    if(this.log.isDebugEnabled()) {
        FormattingTuple ft = MessageFormatter.arrayFormat(format, arguments);
        this.log.debug(ft.getMessage(), ft.getThrowable());
    }
}

但也有一些方法重载不会在内部检查是否启用了给定的登录级别,例如:

public void debug(String msg, Throwable t) {
    this.log.debug(msg, t);
}

另一件事是 Logger 实现可以更改,因此如果您想始终确保根据其日志记录级别调用您的记录器,那么您可能需要考虑使用isDebugEnabled()方法。

于 2015-06-02T09:32:35.993 回答