在一次项目的调试中发现了log4j-over-slf4j.jar 和 slf4j-log4j12.jar 两个jar包存在冲突,于是根据这个问题突引发出如何解决jar包冲突的方法。
首先先还原这个异常:
- 在pom文件中引入,log4j-over-slf4j 和 slf4j-log4j12,如下:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.21</version>
</dependency>
- 然后写一个测试类:
public class DetectedBothLog {
private static Logger logger = LoggerFactory.getLogger(DetectedBothLog.class);
public static void main(String[] args) {
logger.debug("hello, this is a log demo");
}
}
运行后异常如下:
很明显可以看到是jar冲突,为什么这两个jar会冲突了,并且导致的还是堆栈溢出?
在slf4j的官网中其实已经给出了解释:链接。意思是:slf4j-log4j12模块的目的是将对SLF4J的日志委托或重定向到log4j(大家都知道slf4j其实并不具体实现日志的记录)。而同时,log4j-over-slf4j模块的目的是将log4j的日志重定向到SLF4J,那这样一来势必导致循环调用,也就会出现StackOverflowError。
重点来了……
要解决这个问题,只需要排除 slf4j-log4j12.jar即可。但是如何找到这个jar包了?很大部分情况是,这个jar包并不是直接在你的工程pom文件中引入的,它可能是你依赖的一个jar包,而这个依赖的jar包依赖了slf4j-log4j12.jar。那需要找到你真实依赖的jar包,然后exclustion掉。
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
那现在的问题是:如何找到你工程pom文件中依赖的真实jar包?通常有以下几种方法:
第一种:假设你已经知道需要排除的jar的groupId和artifactId
例如,slf4j-log4j12.jar的groupId和artifactId分别是,org.slf4j 和 slf4j-log4j12。那这种情况下,最方面的就是执行如下的一个命令:
mvn dependency:tree -Dverbose -Dincludes=org.slf4j: slf4j-log4j12
这样就可以直接看到slf4j-log4j12.jar是哪个jar包依赖的了。
第二种:就是借助IDE查找
例如使用intelj idea,在安装了dependency analyzer插件后,就可以打开pom文件,然后直接搜索,最后就可以得到它是属于哪个jar.
总结:jar包冲突也是属于程序异常的一种类型,不要忽略它。当遇到后,如何解决jar包冲突,可以用上面两种方法,简单直接