log4j-java.lang.NoSuchFieldError: TRACE

本文分析了因工程jar包依赖多个版本Log4j而导致的日志记录问题。具体表现为高版本与低版本间的不兼容引发的系统错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

at org.jboss.logging.Log4jLoggerPlugin.isTraceEnabled(Log4jLoggerPlugin.java:85)
            at org.jboss.logging.Logger.isTraceEnabled(Logger.java:122)
            at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:622)
            at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:589)
            at javax.naming.InitialContext.lookup(InitialContext.java:351)
            at com.cognizant.util.ServiceHelper.initQueueService(ServiceHelper.java:153)
            at com.cognizant.main.StartUp.<init>(StartUp.java:28)
            at com.cognizant.main.StartUp.main(StartUp.java:46)

 

工程jar包中依赖了多个 log4j 包,而且有高版本和低版本的,导致冲突了。

Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class org.apache.logging.log4j.core.LoggerContext at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.createContext(ClassLoaderContextSelector.java:254) at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.locateContext(ClassLoaderContextSelector.java:218) at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(ClassLoaderContextSelector.java:136) at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(ClassLoaderContextSelector.java:123) at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(ClassLoaderContextSelector.java:117) at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:150) at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:47) at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194) at org.apache.commons.logging.LogAdapter$Log4jLog.<clinit>(LogAdapter.java:155) at org.apache.commons.logging.LogAdapter$Log4jAdapter.createLog(LogAdapter.java:122) at org.apache.commons.logging.LogAdapter.createLog(LogAdapter.java:89) at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:67) at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:59) at org.springframework.boot.SpringApplication.<clinit>(SpringApplication.java:196) at com.zpkj.eps.outernet.OuternetApplication.main(OuternetApplication.java:21) Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.NoSuchFieldError: EMPTY_BYTE_ARRAY [in thread "main"] at org.apache.logging.log4j.core.config.ConfigurationSource.<clinit>(ConfigurationSource.java:59) at org.apache.logging.log4j.core.config.NullConfiguration.<init>(NullConfiguration.java:32) at org.apache.logging.log4j.core.LoggerContext.<clinit>(LoggerContext.java:74) at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.createContext(ClassLoaderContextSelector.java:254) at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.locateContext(ClassLoaderContextSelector.java:218) at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(ClassLoaderContextSelector.java:136) at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(ClassLoaderContextSelector.java:123) at org.apache.logging.log4j.core.selector.ClassLoaderContextSelector.getContext(ClassLoaderContextSelector.java:117) at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:150) at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:47) at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194) at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getContext(AbstractLoggerAdapter.java:138) at org.apache.logging.slf4j.Log4jLoggerFactory.getContext(Log4jLoggerFactory.java:45) at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:48) at org.apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:30) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:363) at reactor.util.Loggers$Slf4JLoggerFactory.getLogger(Loggers.java:205) at reactor.util.Loggers.useSl4jLoggers(Loggers.java:166) at reactor.util.Loggers.resetLoggerFactory(Loggers.java:69) at reactor.util.Loggers.<clinit>(Loggers.java:53) at reactor.core.publisher.Hooks.<clinit>(Hooks.java:550) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at com.intellij.rt.debugger.agent.DebuggerAgent.premain(DebuggerAgent.java:14) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:386) at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401)
05-14
<think>我们正在处理一个Java异常:`java.lang.NoSuchFieldError:Factory`。这个错误通常发生在运行时,当JVM尝试访问一个类的特定字段(在这个案例中是名为`Factory`的字段)时,发现该字段不存在。这往往是由于类路径中存在多个版本的同一个库,而编译时使用的版本和运行时加载的版本不一致导致的。结合用户提供的引用和之前的问题(关于EasyExcel导出报错),我们可以推断这个错误与ApachePOI库的版本冲突有关。具体来说,EasyExcel依赖较高版本的POI(如5.x),而项目中可能同时存在较低版本的POI(如3.x)。在POI3.x中,某些类可能没有`Factory`字段,而POI5.x中引入了这个字段。因此,当代码编译时使用了POI5.x(有`Factory`字段),但运行时加载了POI3.x(没有`Factory`字段),就会抛出`NoSuchFieldError:Factory`。此外,引用[2]提到更换`commons-compress`版本为1.19可以解决某个问题,这提示我们可能还有其他依赖冲突,因为POI也依赖`commons-compress`。解决方案的核心是统一POI库的版本,并排除冲突的依赖。以下是详细的解决步骤:###步骤1:确定冲突的依赖使用Maven命令检查依赖树,找出所有POI相关的依赖及其版本:```bashmvndependency:tree-Dincludes=org.apache.poi```或者,在IDE中(如IntelliJIDEA)可以通过Maven工具窗口查看依赖树。###步骤2:排除旧版本的POI在`pom.xml`中,对引入旧版本POI的依赖进行排除。例如,如果某个依赖传递引入了POI3.x,可以这样排除:```xml<dependency><groupId>some.group</groupId><artifactId>some-artifact</artifactId><version>X.X.X</version><exclusions><exclusion><groupId>org.apache.poi</groupId><artifactId>poi</artifactId></exclusion><exclusion><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId></exclusion><!--排除其他POI相关依赖--></exclusions></dependency>```###步骤3:显式声明所需版本的POI在`pom.xml`中明确指定POI的版本(与EasyExcel兼容的版本,如5.2.5):```xml<properties><poi.version>5.2.5</poi.version></properties><dependencies><!--其他依赖--><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>${poi.version}</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>${poi.version}</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-lite</artifactId><version>${poi.version}</version></dependency><!--注意:根据实际情况,可能还需要其他POI模块--></dependencies>```###步骤4:处理其他相关依赖POI5.x依赖较高版本的`commons-compress`(至少1.19),因此需要确保`commons-compress`的版本也是兼容的。如果项目中其他依赖引入了低版本的`commons-compress`,同样需要排除并统一版本:```xml<dependency><groupId>org.apache.commons</groupId><artifactId>commons-compress</artifactId><version>1.21</version><!--或至少1.19,参考引用[2]--></dependency>```###步骤5:清理和重建项目执行Maven命令清理并重新构建项目:```bashmvncleaninstall-U```###步骤6:验证运行之前出错的导出功能,确认问题是否解决。###原因分析-**根本原因**:类加载时,JVM找到了一个不包含`Factory`字段的旧版本POI类(比如`org.apache.poi.ss.usermodel.WorkbookFactory`)。这是因为类路径中同时存在多个版本的POI,而类加载器加载了旧版本。-**深层原因**:Maven依赖传递导致不同模块引入了不同版本的POI,而Maven的依赖仲裁(nearestwins)可能选择了旧版本。###其他可能原因1.**缓存问题**:如果使用IDE,可能存在编译缓存,尝试清理并重启IDE。2.**部署问题**:确保部署的war/jar包中包含的是正确版本的依赖,检查打包配置(如maven-assembly-plugin或spring-boot-maven-plugin)。3.**作用域问题**:检查依赖的作用域(如`provided`),确保运行时能访问到正确版本的库。###相关问题1.如何查看Maven依赖树中某个依赖的传递路径?2.除了POI,还有哪些库容易引起版本冲突?3.在SpringBoot项目中如何统一管理依赖版本?4.如何调试类加载冲突问题?5.`NoSuchFieldError`和`NoSuchMethodError`有什么区别?[^1]:引用自用户提供的引用[1],虽然与内存溢出相关,但提醒我们注意JVM参数和类加载器数量限制,不过本问题更可能是版本冲突。[^2]:引用[2]提到更换`commons-compress`版本,这可能是解决POI依赖冲突的一部分。</think>### Java `NoSuchFieldError: Factory` 异常原因与解决方案 #### 核心原因分析 该异常的根本原因是 **类路径中存在不兼容的依赖版本冲突**,具体表现为: 1. **POI 版本冲突** Apache POI 库的不同版本(如 3.x 和 5.x)存在二进制不兼容,高版本代码尝试访问低版本中不存在的 `Factory` 字段[^1]。 ```mermaid graph LR A[应用代码] --> B[调用 POI 5.x 的 Factory 字段] C[类加载器] --> D[实际加载 POI 3.x] B -->|运行时| D D -->|无 Factory 字段| E[NoSuchFieldError] ``` 2. **依赖传递冲突** Maven/Gradle 依赖传递导致多个 POI 版本共存(常见冲突组合): | 冲突组件 | 典型版本 | 解决方案 | |-------------------|---------------|--------------------------| | EasyExcel | 需 POI ≥ 5.2 | 排除旧版 POI | | Apache Tika | 常带 POI 3.17 | `<exclusions>` 排除 | | `commons-compress`| 需 ≥ 1.19[^2] | 显式声明新版 | 3. **类加载顺序问题** JVM 优先加载旧版 POI 的类文件(如 `WorkbookFactory`),导致新版功能缺失。 --- #### 完整解决方案 ##### 步骤 1:统一 POI 版本 在 `pom.xml` 中强制指定版本: ```xml <properties> <!-- 使用 EasyExcel 兼容版本 --> <poi.version>5.2.5</poi.version> </properties> <dependencies> <!-- 排除所有旧版 POI --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.3.4</version> <exclusions> <exclusion> <groupId>org.apache.poi</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <!-- 显式声明新版 POI --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>${poi.version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>${poi.version}</version> </dependency> </dependencies> ``` ##### 步骤 2:处理关键传递依赖 ```xml <!-- 修复 commons-compress 冲突 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-compress</artifactId> <version>1.21</version> <!-- 至少 ≥1.19[^2] --> </dependency> <!-- 排除其他模块的旧版 POI --> <dependency> <groupId>org.apache.tika</groupId> <artifactId>tika-core</artifactId> <version>2.9.1</version> <exclusions> <exclusion> <groupId>org.apache.poi</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> ``` ##### 步骤 3:验证依赖树 ```bash mvn dependency:tree -Dincludes=org.apache.poi,org.apache.commons.compress ``` 输出应显示统一版本: ``` [INFO] org.apache.poi:poi:jar:5.2.5:compile [INFO] org.apache.poi:poi-ooxml:jar:5.2.5:compile [INFO] org.apache.commons:commons-compress:jar:1.21:compile ``` ##### 步骤 4:清理重建 ```bash mvn clean install -U # -U 强制更新快照 ``` --- #### 其他场景处理 1. **Spring Boot 项目** 在 `spring-boot-dependencies` 中覆盖 POI 版本: ```xml <properties> <poi.version>5.2.5</poi.version> </properties> ``` 2. **Gradle 项目** ```gradle configurations.all { resolutionStrategy { force 'org.apache.poi:poi:5.2.5' force 'org.apache.poi:poi-ooxml:5.2.5' force 'org.apache.commons:commons-compress:1.21' } } ``` 3. **Web 容器部署** 检查 `WEB-INF/lib` 下是否有旧版 POI JAR 文件(如 `poi-3.17.jar`),手动删除。 --- #### 技术原理 当 JVM 加载类时: 1. 编译期:代码引用 `org.apache.poi.ss.usermodel.WorkbookFactory.Factory` 2. 运行时:类加载器找到旧版 POI 的 `WorkbookFactory` 类 3. 校验失败:旧版类中不存在 `Factory` 字段 4. 抛出 `NoSuchFieldError`(属于 `LinkageError` 子类) --- #### 相关问题 1. 如何定位 Maven 依赖冲突的具体路径? 2. 除了 `NoSuchFieldError`,还有哪些常见依赖冲突异常? 3. Spring Boot 如何管理第三方库的版本冲突? 4. 如何避免多模块项目的传递依赖冲突? 5. `NoSuchFieldError` 和 `ClassNotFoundException` 有何本质区别? [^1]: POI 5.x 的 `Factory` 字段在 3.x 中不存在,导致二进制不兼容 [^2]: `commons-compress` 1.19+ 解决 POI 的底层压缩库兼容性问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值