16

我的 java 项目依赖于不同的 SLF4J 版本。如何抑制烦人的警告?

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:xyz234/lib/slf4j-
log4j12-1.5.8.jar!/org/slf4j/impl/StaticLoggerBinder.class]

SLF4J: Found binding in [jar:file:xyz123/.m2/repository/org/slf4j/slf4j-log4j12
/1.6.0/slf4j-log4j12-1.6.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.

PS:这与关于相同绑定重复的 slf4j 警告不是同一个问题,答案是如何消除误报警告,但在我的情况下这是一个真正的警告。PSS:对不起,我忘了说:我使用 Maven 并且 SLF4J 包含在我的依赖项的依赖项中。

4

6 回答 6

20

从类路径中删除slf4j-log4j12-1.5.8.jar或之一slf4j-log4j12-1.6.0.jar。您的项目不应依赖于不同版本的 SLF4J。我建议你只使用 1.6.0。

如果您使用的是 Maven,则可以排除传递依赖项。这是一个例子:

<dependency>
    <groupId>com.sun.xml.stream</groupId>
    <artifactId>sjsxp</artifactId>
    <version>1.0.1</version>
    <exclusions>
        <exclusion>
            <groupId>javax.xml.stream</groupId>
            <artifactId>stax-api</artifactId>
        </exclusion>
    </exclusions>
</dependency>

使用当前的 slf4j-api 实现是不可能删除这些警告的。该类org.slf4j.LoggerFactory打印消息:

  ...
  if (implementationSet.size() > 1) {
    Util.report("Class path contains multiple SLF4J bindings.");
    Iterator iterator = implementationSet.iterator();
    while(iterator.hasNext()) {
      URL path = (URL) iterator.next();
      Util.report("Found binding in [" + path + "]");
    }
    Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
  }
  ...

Util课程如下:

public class Util {

  static final public void report(String msg, Throwable t) {
    System.err.println(msg);
    System.err.println("Reported exception:");
    t.printStackTrace();
  }
  ...

report方法直接写入System.err. 一种解决方法可能是在第一次通话之前System.err将其替换为,但如果这样做,您可能会丢失其他重要消息。System.setErr() LoggerFactory.getLogger()

当然,您可以下载源代码并删除这些Util.report调用,并在您的项目中使用修改后的 slf4j-api。

于 2011-09-27T15:17:07.777 回答
7
    PrintStream filterOut = new PrintStream(System.err) {
        public void println(String l) {
            if (! l.startsWith("SLF4J")) {
                super.println(l);
            }
        }
    };
    System.setErr(filterOut);

等等!

于 2014-06-20T13:46:56.883 回答
5

您是否阅读了警告所引用的 URL?

SLF4J: See [http://www.slf4j.org/codes.html#multiple_bindings][1] for an explanation.

以下是链接状态:

SLF4J API 旨在一次绑定一个且仅一个底层日志框架。如果类路径上存在多个绑定,SLF4J 将发出警告,列出这些绑定的位置。发生这种情况时,请选择您要使用的唯一一个绑定,然后删除其他绑定。

例如,如果您在类路径上同时具有 slf4j-simple-1.6.2.jar 和 slf4j-nop-1.6.2.jar 并且希望使用 nop(无操作)绑定,则删除 slf4j-simple- 1.6.2.jar 从类路径。

请注意,SLF4J 发出的警告只是一个警告。SLF4J 仍将与它在类路径中找到的第一个框架绑定。

于 2011-09-27T19:16:40.037 回答
1

有时从类路径中排除第二个记录器需要太多的扭曲,并且警告非常烦人。在程序开始时屏蔽标准错误似乎确实有效,例如

    public static void main(String[] args)
    {
        org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.OFF);
        PrintStream old = System.err;
        System.setErr(new PrintStream(new ByteArrayOutputStream()));
        // ... trigger it ...
        System.setErr(old);

        ...

trigger it部分应该调用一些访问日志系统的 nop 函数,否则会导致生成消息。

我不建议将此用于生产代码,但对于 skunkworks 的目的,它应该会有所帮助。

于 2019-03-27T13:35:40.413 回答
1

如果使用 maven 总是使用命令

mvn dependency:tree

这将列出添加到项目中的所有依赖项,包括对我们包含的 jar 的依赖项。在这里,我们可以确定多个版本,或者与添加的其他 jar 一起提供的多个 jar 副本。利用

<exclusions><exclusion><groupId></groupId><artifactId></artifactId></exclusion></exclusions>

<dependency>元素中排除冲突的元素。如果问题仍然存在,请务必在每次排除后重新运行上述 maven 命令。

于 2015-10-07T06:53:47.913 回答
0

如果您使用的是旧版本的 Jetty(例如 Jetty 6),您可能需要更改 webapp 的类加载顺序,使其优先级高于容器的优先级。您可以通过将此行添加到容器的 xml 文件中来做到这一点:

<Set name="parentLoaderPriority">false</Set>
于 2013-02-05T17:03:35.400 回答