升级log4j至2.20.0后出现org.apache.log4j.PropertyConfigurator类找不到问题
问题
在遗留系统代码库中完成以下升级操作:
- 将log4j从1.2.16版本升级至2.20.0版本
- 将Spring Security从4.1.1版本升级至5.2.15版本
已更新的Maven依赖配置如下:
<dependencyManagement> <dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-bom</artifactId> <version>2.20.0</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>5.2.15.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>5.2.15.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-cas</artifactId> <version>5.2.15.RELEASE</version> </dependency> <dependency> <groupId>org.reactivestreams</groupId> <artifactId>reactive-streams</artifactId> <version>1.0.4</version> </dependency>
启动应用时抛出NoClassDefFoundError和ClassNotFoundException,具体堆栈信息:
14:46:10,354 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-5) MSC000001: Failed to start service jboss.deployment.unit."cas-ear-2.1.1-SNAPSHOT.ear".POST_MODULE: org.jboss.msc.service.StartException in service jboss.deployment.unit."cas-ear-2.1.1-SNAPSHOT.ear".POST_MODULE: WFLYSRV0153: Failed to process phase POST_MODULE of deployment "cas-ear-2.1.1-SNAPSHOT.ear" at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:189) at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739) at org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701) at org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559) at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.NoClassDefFoundError: org/apache/log4j/PropertyConfigurator at org.jboss.as.logging.deployments.LoggingConfigDeploymentProcessor.configure(LoggingConfigDeploymentProcessor.java:239) at org.jboss.as.logging.deployments.LoggingConfigDeploymentProcessor.processDeployment(LoggingConfigDeploymentProcessor.java:113) at org.jboss.as.logging.deployments.LoggingConfigDeploymentProcessor.processDeployment(LoggingConfigDeploymentProcessor.java:141) at org.jboss.as.logging.deployments.AbstractLoggingDeploymentProcessor.deploy(AbstractLoggingDeploymentProcessor.java:68) at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:182) ... 8 more Caused by: java.lang.ClassNotFoundException: org.apache.log4j.PropertyConfigurator from [Module "org.jboss.as.logging" version 16.0.1.Final from local module loader @604ed9f0 (finder: local module finder @6a4f787b (roots: C:\wildfly-24\cas\wildfly-24.0.1.Final\modules,C:\wildfly-24\cas\wildfly-24.0.1.Final\modules\system\layers\base))] at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255) at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410) at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398) at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116) ... 13 more
已完成代码中所有log4j相关导入的更新,且代码库中无旧版log4j的直接调用,需排查并修复该问题。
排查修复方案
添加log4j1到log4j2的桥接依赖
WildFly的Logging模块在处理部署时仍尝试加载log4j1.x的API类,需引入桥接依赖让旧API调用转向log4j2实现。在Maven依赖中添加:<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-1.2-api</artifactId> <version>2.20.0</version> </dependency>该依赖会提供
org.apache.log4j.PropertyConfigurator等旧版API类,内部转发到log4j2实现,解决类找不到的问题。修改WildFly部署配置,排除服务器自带的log4j1依赖
在EAR包的META-INF/jboss-deployment-structure.xml中添加配置,排除服务器模块中的log4j1相关依赖,强制使用应用打包的log4j2:<jboss-deployment-structure> <deployment> <exclude-subsystems> <subsystem name="logging"/> </exclude-subsystems> <exclusions> <module name="org.apache.log4j"/> <module name="org.jboss.as.logging"/> </exclusions> <dependencies> <module name="org.apache.logging.log4j" export="true"/> </dependencies> </deployment> </jboss-deployment-structure>替换旧版log4j配置文件
检查部署包中是否存在log4j.properties或log4j.xml,WildFly会自动识别这些旧配置文件并尝试用log4j1的加载器处理。将其替换为log4j2的配置文件(如log4j2.xml或log4j2.yaml),并确保配置格式符合log4j2规范。排查并排除传递依赖中的log4j1
执行Maven命令查看依赖树,找出是否有第三方依赖间接引入了log4j1.x:mvn dependency:tree -Dincludes=log4j:log4j找到后在对应依赖中添加排除配置,例如:
<dependency> <groupId>xxx</groupId> <artifactId>xxx</artifactId> <exclusions> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency>检查服务器启动参数
查看WildFly的启动脚本或VM参数,是否存在针对log4j1的配置参数(如-Dlog4j.configuration),将其替换为log4j2的参数,例如:-Dlog4j.configurationFile=classpath:log4j2.xml
内容的提问来源于stack exchange,提问作者190303458

