tomcat 日志log4j,slf4j,logback冲突

时间:2022-07-27 22:03:06

问题描述:

        启动tomcat,发现tomcat无法启动,catalina.out有如下错误日志:

INFO [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext

 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.listenerStop Exception sending context destroyed event to listener instance of class org.springframework.web.context.ContextLoaderListener

 java.lang.NoClassDefFoundError: Could not initialize class org.apache.log4j.Log4jLoggerFactory

        at org.apache.log4j.LogManager.getLogger(LogManager.java:44)

        at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73)

        at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:270)

        at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:156)

        at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132)

        at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:274)

        at org.springframework.web.context.ContextCleanupListener.<clinit>(ContextCleanupListener.java:43)

        at org.springframework.web.context.ContextLoaderListener.contextDestroyed(ContextLoaderListener.java:145)

        at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4860)

        at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5495)

        at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:224)

        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:159)

        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1407)

        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1397)

        at java.util.concurrent.FutureTask.run(FutureTask.java:266)

        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

        at java.lang.Thread.run(Thread.java:745)

 

 问题分析:

    检查lib库下面,发现今天更新过log4j和logback组合,总共有如下包:

 


slf4j-api-1.7.5.jar

slf4j-log4j12-1.6.1.jar

log4j-1.2.16.jar

log4j-over-slf4j-1.7.5.jar

logback-core-1.1.2.jar

logback-classic-1.1.2.jar

    通过查询资料发现,slf4j-log4j12-1.6.1.jar  和log4j有冲突。


 

解决方法:

      删除后正常,删除这个:slf4j-log4j12-1.6.1.jar  


附件常见组合:

log4j+slf4j

slf4j-api-1.7.5.jar

slf4j-log4j12-1.6.1.jar

log4j-1.2.16.jar



slf4j+logback

logback-core-1.1.2.jar

logback-classic-1.1.2.jar

slf4j-api-1.7.5.jar




还记得上次发版本遇到一个jar包冲突的问题,今天有时间和大家分享下: 
首先在测试环境和P版线上模拟环境都没有出现这样的问题,在正式版上,运维人员给出的堆栈结果如下: 

  1. [19:56:18.083] Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.apache.log4j.Log4jLoggerFactory  
  2. [19:56:18.083]  at org.apache.log4j.Logger.getLogger(Logger.java:39)  
  3. [19:56:18.083]  at com.focustech.redis.util.JsonUtil.<clinit>(JsonUtil.java:22)  
  4. [19:56:18.083]  at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)  
  5. [19:56:18.083]  at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)  
  6. [19:56:18.083]  at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)  
  7. [19:56:18.083]  at java.lang.reflect.Constructor.newInstance(Constructor.java:513)  
  8. [19:56:18.083]  at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:82)  
  9. [19:56:18.083]  at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:59)  
  10. [19:56:18.083]  at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:52)  
  11. [19:56:18.083]  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:639)  
  12. [19:56:18.083]  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:625)  
  13. [19:56:18.083]  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)  
  14. [19:56:18.083]  ... 21 more  


对于这样的错误堆栈,我们首先排查了是不是少这个jar包,但是发现其实这个jar包是有的,并且类也是有的,所以我们又继续排查是不是jar包冲突引起的问题,发现应用的pom文件中与该类相关的只有一个这样的类,不会有多个,所以又派出jar包冲突的问题,所以暂时进行的日志的改造,但是结果还是报这样的错误。 
就在这个时候我试图到log中查找其他的信息,这个时候发现在容器的system error文件中发现有这样的错误堆栈 
  1. SLF4J: Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting *Error.   
  2. SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.  

这个时候我们才发现可能是这两个jar包搞的鬼,所以我百度下了,确实这两个jar包一起会报这样的错误 
具体原因该文章分析的很好,可以学习下 
http://www.tuicool.com/articles/INveIf  

通过这次比较囧的经历,首先,在遇到问题的时候要从多个日志输出文件中去找问题,一般有很多runtime error都打在容器的error日志文件中,其次要多了解一些框架的原理!




可能出现的异常:

发现配置的logback.xml文件没有起作用,于是分析了一下启动log,发现log中出现了SLF4J冲突异常:

  1. SLF4J: Class path contains multiple SLF4J bindings.
  2. SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”

原因分析:

既然是冲突,那可能就是项目中依赖了多个不同版本的slf4j类库,那如何分析到底是哪几个类库依赖了slf4j呢?我们可以使用dependency:tree命令:

$ mvn dependency:tree

解决:

经过依赖tree的分析,发现Zookeeper和Dubbo类库各自都引用了slf4j类库,于是使用<exclusions>标签排除掉传递依赖。

  <dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.8.4</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>

其它各种依赖冲突都可以使用这种方式解决。