SLF4J api 和 binding jar 版本不兼容导致的 IllegalAccessError

 

这是前几天碰到的一个由 SLF4J 引发的异常

Exception in thread "main" java.lang.IllegalAccessError: tried to access field
org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
   at org.slf4j.LoggerFactory.<clinit>(LoggerFactory.java:60)

在网上搜索时,找到了 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 Foo {
    private static final Logger logger = LoggerFactory.getLogger(Foo.class);
    // ... methods
}

 在获取 Logger 时抛了前面的异常。

 

下面通过源码分析下异常的来源:

在 slf4j-api 的早期版本(1.5.5 及之前)中,org.slf4j.LoggerFactory 中包含一个 ILoggerFactory 的 static 属性,并且通过 static 块进行初始化。

public final class LoggerFactory {

  static ILoggerFactory loggerFactory;

  static {
      try { 
        loggerFactory = StaticLoggerBinder.SINGLETON.getLoggerFactory();
      } catch(NoClassDefFoundError ncde) {
      //...
   }
}

 在早期版本的 slf4j binding 实现中,org.slf4j.impl.StaticLoggerBinder 类中的 SINGLETON 成员是被定义为 public 的。

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 私有属性,就会产生前面的异常信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值