log4j2 2.13及以上版本配合maven assembly打包后启动报错如何解决
问题根因
- 核心原因是
maven-assembly-plugin打包时的文件覆盖机制导致Log4j2插件丢失:从Log4j2 2.x版本开始,框架内置的转换器、配置工厂等插件都会统一记录在META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat缓存文件中,log4j-core、log4j-1.2-api等多个Log4j2相关依赖包中都存在该文件,而maven-assembly-plugin默认对同名文件采取直接覆盖的处理逻辑,最终打包出来的jar包中只会保留最后加载的依赖的那份插件缓存文件,其余的都被覆盖丢失。 - 从debug日志可以验证该问题:
PluginManager 'Converter' found 2 plugins是核心异常信号,正常Log4j2环境下Converter插件数量至少有几十种,丢失插件后自然无法识别%d、%thread、%msg等标准格式占位符,也找不到XML配置的解析工厂,进而报配置加载失败的错误。 - 低版本2.13之前运行正常的原因是Log4j2在2.13版本对插件加载逻辑做了调整,取消了旧版本中缺失插件缓存时的兜底扫描逻辑,强制依赖缓存文件加载插件,因此升级后冲突问题直接暴露。
解决方案
方案1:替换为maven-shade-plugin打包(更推荐)
maven-shade-plugin支持自定义文件合并策略,Log4j2官方提供了专门的合并转换器处理插件缓存文件的冲突,替换assembly的配置示例如下:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <!-- 合并Log4j2插件缓存文件 --> <transformer implementation="com.github.edwgiz.maven_shade_plugin.log4j2_cache_transformer.PluginsCacheFileTransformer"> </transformer> <!-- 配置主类 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>testlog4j.Tester</mainClass> <manifestEntries> <Multi-Release>true</Multi-Release> </manifestEntries> </transformer> <!-- 合并META-INF/services下的服务发现文件 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> </configuration> </execution> </executions> <dependencies> <!-- 引入Log4j2插件缓存合并的依赖 --> <dependency> <groupId>com.github.edwgiz</groupId> <artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId> <version>2.14.1</version> </dependency> </dependencies> </plugin>
方案2:继续使用maven-assembly-plugin
需要自定义assembly打包描述符,配置对Log4j2相关同名文件的合并策略:
- 在src/main/assembly下创建自定义描述符文件
jar-with-dependencies.xml - 在文件中添加如下合并规则:
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.1 http://maven.apache.org/xsd/assembly-2.1.1.xsd"> <id>jar-with-dependencies</id> <formats> <format>jar</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <dependencySets> <dependencySet> <outputDirectory>/</outputDirectory> <useProjectArtifact>true</useProjectArtifact> <unpack>true</unpack> <scope>runtime</scope> </dependencySet> </dependencySets> <containerDescriptorHandlers> <!-- 合并服务发现文件 --> <containerDescriptorHandler> <handlerName>metaInf-services</handlerName> </containerDescriptorHandler> <!-- 合并Log4j2插件缓存文件 --> <containerDescriptorHandler> <handlerName>log4j2-plugins</handlerName> </containerDescriptorHandler> </containerDescriptorHandlers> </assembly>
- 修改pom中assembly-plugin的配置,替换原来的descriptorRef为自定义的描述符路径:
<configuration> <archive> <manifest> <mainClass>testlog4j.Tester</mainClass> </manifest> <manifestEntries> <Multi-Release>true</Multi-Release> </manifestEntries> </archive> <descriptors> <descriptor>src/main/assembly/jar-with-dependencies.xml</descriptor> </descriptors> </configuration>
额外配置检查
如果调整打包配置后仍报配置文件找不到的错误,需要确认:
- 若log4j2.xml放在项目resources目录下,启动参数修改为
-Dlog4j.configurationFile=classpath:log4j2.xml - 若log4j2.xml放在jar包外的同级目录,启动参数修改为
-Dlog4j.configurationFile=./log4j2.xml
内容的提问来源于stack exchange,提问作者Nicolas
相关产品推荐
相关产品推荐

