SLF4J api 和 binding jar 版本不兼容导致的 IllegalAccessError
在网上搜索时,找到了 SLF4J FAQ 这篇文档,其中就有对这个异常的描述,当时是把问题解决了。为了将这个问题的解决过程描述方便,我先写了之前的一篇文章,简单介绍了一些 SLF4J 的知识。因为这个异常的产生原因是由于 slf4j-api.jar 与 slf4j-log4j12.jar 版本不兼容所致,其中 slf4j-log4j12.jar 是 SLF4J 提供的五种 binding jar 之一。具体的说,是由于使用了较老版本的 slf4j-api.jar(在我的应用里引的版本是 1.4.1),和较新版本的 slf4j binding jar(在我的应用里引了 slf4j-log4j12-1.5.6.jar)。
?
错误的出处是:?我定义了一个类,为了使用 log4j 打印日志,调用 org.slf4j.LoggerFactory 创建了一个 Logger,并作为类的 static 属性,除此之外无其他的成员属性,代码如下:
public class StaticLoggerBinder { /** * The unique instance of this class. */ public static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder(); public ILoggerFactory getLoggerFactory() { //... }}
?所以,如果 slf4j-api.jar 和 slf4j-log4j12.jar 都使用早期版本,将不会报错。
?
从 SLF4J 1.5.6 开始, slf4j binding 实现中的?org.slf4j.impl.StaticLoggerBinder 类的 SINGLETON 被定义为了 private. 并且从这个版本开始,slf4j api 中 org.slf4j.LoggerFactory 不再使用?StaticLoggerBinder.SINGLETON.getLoggerFactory() 的方式获取 ILoggerFactory 的实例,而是通过?StaticLoggerBinder.getSingleton.getLoggerFactory() 的方式对?ILoggerFactory 实例进行初始化。具体的实现要比早期版本复杂的多,在此不详细列代码了。
?
所以,如果使用早期版本的 slf4j-api.jar 和新版本的 slf4j binding jar,由于?org.slf4j.LoggerFactory 无法访问新版本 binding 实现中的?StaticLoggerBinder.SINGLETON 私有属性,就会产生前面的异常信息。