Could not initialize class org.apache.log4j.Log4

(一) 现象与解决方法

前些天在进行storm job的开发时候忽然报了一个错误,记录一下html

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

固然咱们的第一个反应是log4j这个包缺失(固然也有这种状况,须要首先确认),打开pom文件查看依赖,文件确实存在。java

后经网上搜索加边上大牛指点发现:数据库

log4j-over-slf4j.jar 和 slf4j-log4j12.jar 在同一个classpath下就会出现这个错误。apache

解决方法: 
将slf4j-log4j12.jar从相关的jar中排除工具

(二) 日志组件tips

那么问题来了,为啥会有这种冲突呢?在这里须要简单的说一下log的故事!spa

(1)common-logging、log4j、slf4j、logback.net

common-logging 
common-logging是apache提供的一个通用的日志接口;开放源代码

在common-logging中,有一个Simple logger的简单实现,可是它功能很弱,因此使用common-logging,一般都是配合着log4j来使用;设计

common-logging会经过动态查找的机制,在程序运行时自动找出真正使用的日志库,而且尽量找到一个”最合适”的日志实现类,若是判断有Log4j包,则使用log4j,最悲观的状况下也总能保证提供一个日志实现(SimpleLog)日志

log4j 
Apache的一个开放源代码项目,实现了输出到控制台、文件、 回滚文件、发送日志邮件、输出到数据库日志表、自定义标签等全套功能,且配置比较简单;

slf4j 
slf4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各类各样的日志系统。按照官方的说法,SLF4J是一个用于日志系统的简单Facade,容许最终用户在部署其应用时使用其所但愿的日志系统。能够这么说,slf4j等于commons-logging,是各类日志实现的通用入口,会根据classpath中存在下面哪个Jar来决定具体的日志实现库;

logback 
logback是由log4j创始人设计的又一个开源日志组件。logback当前分红三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个 改良版本。此外logback-classic完整实现SLF4J API使你能够很方便地更换成其它日志系统如log4j。

(2)log4j-over-slf4j.jar 和 slf4j-log4j12.jar 在同一个classpath下为什么出现错误?

在java领域日志工具中,最先获得普遍使用的是 log4j。那么为啥有common-logging的出现?上面已经介绍了common-logging只提供log的接口,其中具体的实现时动态绑定的,因此common-logging与log4j的结合比较多!可是随之也产生了一些问题,那就是common-logging的动态绑定有时候也会失败(说实在这个我也不懂,但愿求解),在这样的背景下slf4j应运而生,slf4j与common-logging同样提供log接口,可是slf4j是经过静态绑定实现。

好的,先在来讲slf4j-log4j12.jar是干啥的? 
slf4j提供 log 接口,其具体实现是根据放入程序的绑定器决定

slf4j-XXX-version.jar

slf4j-log4j12.jar就是实现经过slf4j调度使用log4j

那么log4j-over-slf4j.jar是干啥的勒?

在这里须要引入桥接器的概念,所谓的桥接器就是一个假的日志实现工具。

XXX-over-slf4j.jar

log4j-over-slf4j.jar就是桥接器,原本组件是经过log4j输出日志的,经过该桥接器被转到slf4j,slf4j在根据绑器把日志交给具体的日志实现工具。

若是log4j-over-slf4j.jar 和 slf4j-log4j12.jar共存的后果是什么?那就是两个踢球的人在互相传球,就是没人射门,陷入死循环。

这里写图片描述

参考博文:  [1]http://blog.csdn.net/feng27156/article/details/36885387  [2]http://www.blogjava.net/daiyongzhi/archive/2014/04/13/412364.html