这是前几天碰到的一个由 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 私有属性,就会产生前面的异常信息。
相关推荐
压缩包内的文件名称列表中,"slf4j-api-1.5.8.jar"是SLF4J API的1.5.8版本,而"slf4j-nop-1.5.8.jar"则是SLF4J NOP实现的同版本。这两个JAR文件通常会一起使用,API JAR提供日志接口,NOP JAR作为默认的日志实现。...
slf4j-api.jar slf4j-api.jar slf4j-api.jar slf4j-api.jar
描述中提到的"slf4j-api-1.7.30.jar"同样强调了这个版本的SLF4J API,它提供了API接口,但并不包含实际的日志实现。为了使日志工作,开发者还需要选择并引入一个具体的日志实现库,例如Logback或Log4j,通过在类路径...
总之,`slf4j-api-1.7.7.jar`是SLF4J API的一个版本,它为开发者提供了一个灵活的日志接口,允许在不同的日志框架之间轻松切换,提高了代码的可维护性和部署的便捷性。在实际使用时,需要结合具体的日志实现库,才能...
1.7.21-sources.jar 7、osgi-over-slf4j-1.7.21.jar 8、osgi-over-slf4j-1.7.21-sources.jar 9、slf4j-android-1.7.21.jar 10、slf4j-android-1.7.21-sources.jar 11、slf4j-api-1.7.21.jar 12、slf4j-api-1.7.21-...
`slf4j-api.jar`是SLF4J的核心API,包含了各种日志记录方法和接口,允许开发者在不依赖具体日志实现的情况下编写代码。 在描述中提到的`mina`框架,全称为Apache MINA(Model-View-Controller for Network ...
"slf4j-api-1.7.12.jar"则是SLF4J的核心API库,包含了所有SLF4J的日志记录方法和接口,但不包含任何实际的日志实现。 在Java项目中,通常需要同时包含这两个JAR文件:slf4j-api-1.7.12.jar(提供接口)和slf4j-log4...
SLF4J(Simple Logging Facade for...`slf4j-api-1.7.12.jar`和`slf4j-log4j12-1.7.12.jar`分别是SLF4J API和SLF4J到Log4j的绑定,它们共同工作,使开发者能够利用Log4j的强大功能,同时保持代码与具体日志系统的分离。
赠送jar包:slf4j-api-1.7.16.jar; 赠送原API文档:slf4j-api-1.7.16-javadoc.jar; 赠送源代码:slf4j-api-1.7.16-sources.jar; 赠送Maven依赖信息文件:slf4j-api-1.7.16.pom; 包含翻译后的API文档:slf4j-api-...
赠送jar包:slf4j-api-1.7.32.jar; 赠送原API文档:slf4j-api-1.7.32-javadoc.jar; 赠送源代码:slf4j-api-1.7.32-sources.jar; 赠送Maven依赖信息文件:slf4j-api-1.7.32.pom; 包含翻译后的API文档:slf4j-api-...
slf4j-api-1.6.0.jar,slf4j-jdk14-1.6.0.jar,slf4j-log4j12-1.6.0-rc0.jar,slf4j-nop-1.6.0.jar,slf4j-simple-1.6.0.jar
赠送jar包:slf4j-api-1.7.30.jar; 赠送原API文档:slf4j-api-1.7.30-javadoc.jar; 赠送源代码:slf4j-api-1.7.30-sources.jar; 赠送Maven依赖信息文件:slf4j-api-1.7.30.pom; 包含翻译后的API文档:slf4j-api-...
在`slf4j-api-1.7.25.jar`文件中,包含了SLF4J的所有核心接口和类,如`org.slf4j.Logger`、`org.slf4j.LoggerFactory`和`org.slf4j.Marker`等。这些接口定义了日志记录的基本操作,如`trace()`, `debug()`, `info()`...
描述中提到的"slf4j-api-1.7.26.jar"是SLF4J API的核心库,它包含所有开发者需要使用的接口和类,例如`org.slf4j.Logger`和`org.slf4j.LoggerFactory`。`Logger`接口提供了不同级别的日志记录方法,如`trace()`, `...
赠送jar包:slf4j-api-1.7.26.jar; 赠送原API文档:slf4j-api-1.7.26-javadoc.jar; 赠送源代码:slf4j-api-1.7.26-sources.jar; 赠送Maven依赖信息文件:slf4j-api-1.7.26.pom; 包含翻译后的API文档:slf4j-api-...
1.7.21-sources.jar 7、osgi-over-slf4j-1.7.21.jar 8、osgi-over-slf4j-1.7.21-sources.jar 9、slf4j-android-1.7.21.jar 10、slf4j-android-1.7.21-sources.jar 11、slf4j-api-1.7.21.jar 12、slf4j-api-1.7.21-...
与slf4j-nop-1.7.25.jar相匹配的版本信息slf4j-api-1.7.25.jar
"slf4j-api-1.7.28.jar"是SLF4J API的特定版本,这里是1.7.28版。这个JAR文件包含了SLF4J API的所有类和接口,供开发者在他们的应用中引用和使用。通过导入这个库,开发者可以编写与具体日志实现无关的代码,只需...
11、slf4j-api-1.7.21.jar 12、slf4j-api-1.7.21-sources.jar 13、slf4j-ext-1.7.21.jar 14、slf4j-ext-1.7.21-sources.jar 15、slf4j-jcl-1.7.21.jar 16、slf4j-jcl-1.7.21-sources.jar 17、slf4j-jdk14-...
在描述中提到的"lombok.extern.slf4j.Slf4j注解错误",这可能是指在使用Lombok和SLF4J时遇到的一些问题,例如缺少对应的依赖、配置错误或者版本不兼容。为了解决这些问题,通常需要检查以下几点: 1. 确保项目中已...