Java 11环境下Log4j2日志文件写入失效问题求助
核心原因推测
从Java 8+Wildfly 10迁移到Java 11+Wildfly 15后日志文件无内容,核心问题大概率和Wildfly日志子系统的接管、Log4j2配置不兼容、Java模块化影响这三点相关,以下是具体分析和解决步骤:
1. Wildfly 15日志子系统接管应用日志输出
Wildfly 15默认使用JBoss Logging作为全局日志门面,会自动接管应用中的Log4j2、SLF4J等日志框架输出,导致应用自定义的RollingFileAppender无法生效,日志被路由到Wildfly自身的日志系统(如standalone/log/server.log)。
解决办法:
在应用的WEB-INF目录下创建jboss-deployment-structure.xml,排除Wildfly的日志相关模块,强制应用使用自身的Log4j2依赖:
<jboss-deployment-structure> <deployment> <exclusions> <module name="org.jboss.logging"/> <module name="org.apache.log4j"/> <module name="org.slf4j"/> <module name="org.slf4j.impl"/> </exclusions> <dependencies> <module name="javax.api"/> </dependencies> </deployment> </jboss-deployment-structure>
2. Log4j2 RollingFileAppender配置不完整
你提供的log4j2.xml中RollingFileAppender缺少触发策略和滚动策略的配置,虽然Wildfly 10时代可能兼容这种不完整配置,但Wildfly 15搭配Java 11时,Log4j2的初始化验证更严格,导致Appender虽能创建文件但无法写入日志。
解决办法:
补全RollingFileAppender的必要配置,示例如下:
<RollingFile name="File" fileName="/tmp/log4j2.log" filePattern="/tmp/log4j2-%d{yyyy-MM-dd}-%i.log"> <PatternLayout> <Pattern>%d{HH:mm:ss.SSS} [%t] %-5level - %msg%n</Pattern> </PatternLayout> <!-- 当文件达到10MB时触发滚动 --> <SizeBasedTriggeringPolicy size="10MB"/> <!-- 最多保留10个滚动日志文件 --> <DefaultRolloverStrategy max="10"/> </RollingFile>
3. Java 11模块化(JPMS)的类加载影响
Java 11启用了模块系统(JPMS),如果你的应用是模块化的,Log4j2的API和Core模块可能未被正确声明依赖,导致应用无法加载完整的Log4j2实现。
解决办法:
- 若应用为模块化项目,在
module-info.java中添加依赖声明:module your.app.module { requires org.apache.logging.log4j; requires org.apache.logging.log4j.core; // 其他模块依赖... } - 若为非模块化项目,确保
log4j-core-2.17.1.jar被正确打包到应用的WEB-INF/lib目录,且未被Wildfly的全局模块覆盖。
4. 初始化顺序与配置文件加载问题
Wildfly 15的类加载机制较Wildfly 10有变化,可能导致Log4j2无法正确加载配置文件,或者初始化时机晚于日志调用。
解决办法:
- 确保
log4j2.xml放置在WEB-INF/classes目录(Web应用)或类路径根目录; - 在Wildfly启动参数中显式指定Log4j2配置文件:
-Dlog4j.configurationFile=classpath:log4j2.xml - 必要时在代码中显式初始化Log4j2:
import org.apache.logging.log4j.core.config.Configurator; import org.apache.logging.log4j.core.config.ConfigurationSource; import java.io.FileInputStream; // 在应用启动时执行 ConfigurationSource source = new ConfigurationSource(new FileInputStream("classpath:log4j2.xml")); Configurator.initialize(null, source);
内容的提问来源于stack exchange,提问作者Pete Long

