从Tomcat 8升级到Tomcat 10后Log4j异常问题求助
问题解决方案
针对问题1:StackOverflowError 循环调用异常
这个异常是类加载器与日志初始化的循环依赖导致的:WebappClassLoader加载Spring Boot的Log4j2LoggingSystem时,触发JUL日志检查,而JUL又调用WebappClassLoader的类加载逻辑,形成死循环。
解决步骤:
- 废弃Tomcat/lib下自定义
jars文件夹的方式,Tomcat10的类加载机制对容器级依赖的管理更严格,不建议自定义目录扩展类路径。 - 将所有Log4j2相关jar包直接放置到
%CATALINA_HOME/lib目录下,后续通过JVM参数统一配置日志桥接。
针对问题2:ClassNotFoundException(log4j-jul类找不到)
报错的核心是JUL的LogManager初始化早于Tomcat的Catalina类加载器启动:JDK17中,java.util.logging.LogManager是由启动类加载器(Bootstrap/AppClassLoader)初始化的,而%CATALINA_HOME/lib下的jar是由Tomcat的Catalina类加载器加载的,启动类加载器无法访问这些类。
解决步骤:
- 将
log4j-jul-2.20.0.jar复制到JDK的扩展目录:$JAVA_HOME/jmods(JDK17推荐)或者$JAVA_HOME/lib/ext(兼容方式)。 - 或者在Tomcat的启动脚本(
catalina.bat/catalina.sh)中,添加JVM参数将Log4j相关jar加入启动类路径:
注意:需要把所有依赖的Log4j核心jar都包含进去,避免后续依赖缺失。set JAVA_OPTS=%JAVA_OPTS% -cp "%CATALINA_HOME/lib/log4j-api-2.20.0.jar;%CATALINA_HOME/lib/log4j-jul-2.20.0.jar" - 在
%CATALINA_HOME/conf/logging.properties中,替换默认LogManager:logManager=org.apache.logging.log4j.jul.LogManager
针对问题3:部分Spring Boot组件日志丢失
日志丢失是因为Spring Boot3的Log4j2上下文与Tomcat的JUL桥接未正确同步,导致部分组件的日志事件未被Log4j2捕获。
解决步骤:
- 确保Spring Boot项目中排除默认的JUL依赖,添加Log4j2桥接依赖(在pom.xml中):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jul</artifactId> <version>2.20.0</version> <scope>runtime</scope> </dependency> <!-- 排除Spring Boot默认的日志依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> - 在Tomcat启动脚本中添加JVM参数,强制Log4j2接管JUL日志:
set JAVA_OPTS=%JAVA_OPTS% -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector - 确保项目中的
log4j2.xml/log4j2.properties配置了足够的日志级别,比如对Spring Boot核心包开启DEBUG/INFO级别:<Logger name="org.springframework" level="INFO" additivity="false"> <AppenderRef ref="Console"/> <AppenderRef ref="File"/> </Logger>
内容的提问来源于stack exchange,提问作者user2028936
相关产品推荐
相关产品推荐

