如何抑制SLF4J关于多个绑定的警告?

时间:2011-09-27 15:14:18

标签: maven binding warnings slf4j suppress

我的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.

P.S。:这与slf4j warning about the same binding being duplicate的问题不同,答案是如何摆脱误报警告,但在我的情况下,这是一个真正的警告。 P.S.S。:抱歉,我忘了提及:我使用Maven,SLF4J包含在我的依赖项的依赖项中。

6 个答案:

答案 0 :(得分:20)

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

如果你正在使用Maven,你可以exclude transitive dependencies。这是一个例子:

<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>

使用current slf4j-api implementation无法删除这些警告。 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。

答案 1 :(得分:5)

您是否阅读了警告引用的网址?

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   仍将与它在类路径上找到的第一个框架绑定。

答案 2 :(得分:3)

    PrintStream filterOut = new PrintStream(System.err) {
        public void println(String l) {
            if (! l.startsWith("SLF4J")) {
                super.println(l);
            }
        }
    };
    System.setErr(filterOut);

etvoilà!

答案 3 :(得分:1)

如果使用maven,请始终使用命令

mvn dependency:tree

这将列出添加到项目中的所有依赖项,包括我们包含的jar的依赖项。在这里,我们可以指出多个版本,或多个副本的罐子与其他添加的罐子。使用

<exclusions><exclusion><groupId></groupId><artifactId></artifactId></exclusion></exclusions>
<dependency>元素中

排除那些冲突的元素。如果问题仍然存在,请务必在每次排除后重新运行上面的maven命令。

答案 4 :(得分: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函数来访问日志记录系统,否则将导致生成消息。

我不建议将其用于生产代码,但出于臭鼬的目的,它应该会有所帮助。

答案 5 :(得分:0)

如果你使用旧版本的Jetty(比如Jetty 6),你可能需要更改webapp的类加载顺序,使其优先于容器的优先级。您可以通过将此行添加到容器的xml文件来执行此操作:

<Set name="parentLoaderPriority">false</Set>