我的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包含在我的依赖项的依赖项中。
答案 0 :(得分:20)
从类路径中删除slf4j-log4j12-1.5.8.jar
或slf4j-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>