Slf4j 简明教程

SLF4J - Error Messages

在本章中,我们将讨论在使用 SLF4J 时收到的各种错误消息或警告,以及这些消息的原因/含义。

Failed to load class "org.slf4j.impl.StaticLoggerBinder".

当类路径中没有提供 SLF4J 绑定时,会引发此警告。

以下是完整的警告 −

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further
details.

要解决此问题,您需要添加日志记录框架绑定之一。这是在本教程的 Hello world 章中进行说明的。

Note − 这种情况发生在 SLF4J 1.6.0 至 1.8.0-beta2 之间的版本中。

No SLF4J providers were found

在 slf4j-1.8.0-beta2 中,上述警告更清楚地说 “No SLF4J providers were found”

以下是完整的警告 −

SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.

Classpath contains SLF4J bindings targeting slf4j-api versions prior to 1.8

如果您使用的是 SLF4J 1.8 版本,并且您在类路径中具有以前版本的绑定,但没有 1.8 的绑定,您将看到如下所示的警告。

SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.
SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions prior to
1.8.
SLF4J: Ignoring binding found at
[jar:file:/C:/Users/Tutorialspoint/Desktop/Latest%20Tutorials/SLF4J%20Tutorial/
slf4j-1.7.25/slf4j-jdk14-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#ignoredBindings for an explanation.

NoClassDefFoundError: org/apache/commons/logging/LogFactory

如果您使用 slf4j-jcl ,并且您在类路径中只有 slf4j-jcl.jar ,您将收到如下所示的异常。

Exception in thread "main" java.lang.NoClassDefFoundError:
org/apache/commons/logging/LogFactory
   at org.slf4j.impl.JCLLoggerFactory.getLogger(JCLLoggerFactory.java:77)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:358)
   at SLF4JExample.main(SLF4JExample.java:8)
Caused by: java.lang.ClassNotFoundException:
org.apache.commons.logging.LogFactory
   at java.net.URLClassLoader.findClass(Unknown Source)
   at java.lang.ClassLoader.loadClass(Unknown Source)
   at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
   at java.lang.ClassLoader.loadClass(Unknown Source)
   ... 3 more

为了解决此问题,你需要将 commons-logging.jar 添加到你的 classpath 中。

Detected both jcl-over-slf4j.jar AND bound slf4j-jcl.jar on the classpath..

绑定 slf4j-jcl.jar 将 SLF4J 日志记录器的调用重定向到 JCL,绑定 jcl-over-slf4j.jar 将 JCL 日志记录器的调用重定向到 SLF4J。因此,在项目的 classpath 中无法同时拥有这两者。如果你这样做,将会收到类似于以下内容的异常。

SLF4J: Detected both jcl-over-slf4j.jar AND bound slf4j-jcl.jar on the class
path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#jclDelegationLoop for more
details.
Exception in thread "main" java.lang.ExceptionInInitializerError
   at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:71)
   at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:42)
   at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
   at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
   at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
   at SLF4JExample.main(SLF4JExample.java:8)
Caused by: java.lang.IllegalStateException: Detected both jcl-over-slf4j.jar
AND bound slf4j-jcl.jar on the class path, preempting StackOverflowError. See
also http://www.slf4j.org/codes.html#jclDelegationLoop for more details.
   at org.slf4j.impl.JCLLoggerFactory.<clinit>(JCLLoggerFactory.java:54)
   ... 7 more

为了解决此问题,删除这两个 jar 文件中的任意一个。

Detected logger name mismatch

你可以通过下列方式创建日志记录器对象:

  1. 将要创建的日志记录器的名称作为参数传递给 getLogger() 方法。

  2. 将类作为参数传递给此方法。

如果你试图通过将类作为参数传递来创建日志记录器工厂对象,而且你将系统属性 slf4j.detectLoggerNameMismatch 设置为 true,那么你传递给 getLogger() 方法的参数所属类的名称和你使用的类应当相同,否则你会收到下列警告:

“检测到日志记录器名称不匹配。

考虑以下示例。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SLF4JExample {
   public static void main(String[] args) {
      System.setProperty("slf4j.detectLoggerNameMismatch", "true");

      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger(Sample.class);

      //Logging the information
      logger.info("Hi Welcome to Tutorilspoint");
   }
}

在此,我们已将 slf4j.detectLoggerNameMismatch 属性设置为 true。我们使用的类名为 SLF4JExample ,而我们传递给 getLogger() 方法的类名为 Sample ,由于这两个名称不相等,因此会收到以下警告。

SLF4J: Detected logger name mismatch. Given name: "Sample"; computed name:
"SLF4JExample".
SLF4J: See http://www.slf4j.org/codes.html#loggerNameMismatch for an
explanation
Dec 10, 2018 12:43:00 PM SLF4JExample main
INFO: Hi Welcome to Tutorilspoint

Note - 这发生在 SLF4J 1.7.9 之后

Classpath contains multiple SLF4J bindings.

你应该在 classpath 中只保留一个绑定。如果你有多个绑定,你将会收到一条警告,列出这些绑定及其位置。

假设 classpath 中有绑定 slf4j-jdk14.jarslf4j-nop.jar ,那么我们将会收到以下警告。

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in
[jar:file:/C:/Users/Tutorialspoint/Desktop/Latest%20Tutorials/SLF4J%20Tutorial/
slf4j-1.7.25/slf4j-nop-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in
[jar:file:/C:/Users/Tutorialspoint/Desktop/Latest%20Tutorials/SLF4J%20Tutorial/
slf4j-1.7.25/slf4j-jdk14-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an
explanation.
SLF4J: Actual binding is of type [org.slf4j.helpers.NOPLoggerFactory]

Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path

要将 Log4j 日志记录器调用重新定向到 SLF4J,你需要使用 log4j-over-slf4j.jar 绑定,如果你想将 SLF4J 调用重新定向到 Log4j,则需要使用 slf4j-log4j12.jar 绑定。

因此,你不能在 classpath 中同时拥有两者。如果你这样做,你会收到以下异常。

SLF4J: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the
class path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more
details.
Exception in thread "main" java.lang.ExceptionInInitializerError
   at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:72)
   at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:45)
   at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
   at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
   at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
   at SLF4JExample.main(SLF4JExample.java:8)
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar
AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError.
See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.