使用maven构建项目时,如果项目中有log4j的依赖,在运行程序时可能会出现在同一个类中log4j-over-slf4j.jar和 slf4j-log4j12.jar冲突的问题:
错误原因:
Exception in thread "main" java.lang.ExceptionInInitializerError
at org.apache.log4j.LogManager.getLogger(LogManager.java:44)
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:66)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:270)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:657)
at org.apache.hadoop.conf.Configuration.<clinit>(Configuration.java:173)
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
at org.apache.log4j.Log4jLoggerFactory.<clinit>(Log4jLoggerFactory.java:49)
... 8 more
原因是:log4j-over-slf4j和slf4j-log4j12是跟Java日志系统相关的两个jar包,当它们同时出现在classpath下时,就可能会引起堆栈溢出异常。
解决办法:pom.xml文件中,在使用到的依赖包中添加<exclusion>标签将slf4j-log4j12.jar排除即可,但是我们一个一个找到排除会很麻烦,所以我们使用IDEA插件Maven Helper解决这个问题,就会方便更多。
点击Install
然后重新启动IDEA,安装完成后,在 pom 文件下方会出现这个东西,然后点击这个,
接下来到重点了,选中冲突选项 conflicts,这一列都是存在冲突的包,
我然后根据冲突的包把它排除掉,当然我们调错误的时候也可以直接搜索有问题的包,我出现的那个错误:log4j-over-slf4j.jar,我已经排除掉了。这里我以lombok为例
选中右键就可以 Exclude 啦,想用1.16.12就把其他版本的Exclude掉,想用0.11.6就把其他版本的Exclude掉,是不是很方便。
面对众多的依赖,有一种方法不用考虑依赖路径、声明优化等因素可以采用直接锁定版本的方法确定依赖构件的版本,版本锁定后则不考虑依赖的声明顺序或依赖的路径,以锁定的版本的为准添加到工程中,此方法在企业开发中常用。
如下的配置是锁定了spring-beans和spring-context的版本
<dependencyManagement>
<dependencies>
<!--这里锁定版本为4.2.4 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
注意:在工程中锁定依赖的版本并不代表在工程中添加了依赖,如果工程需要添加锁定版本的依赖则需要单独添加<dependencies></dependencies>标签,如下:
<dependencies>
<!--这里是添加依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
上边添加的依赖并没有指定版本,原因是已在<dependencyManagement>中锁定了版本,所以在<dependency>下不需要再指定版本。