Mule-3.3.1与log4j-1.2-api桥接引发无限递归,如何解决?
Mule 3.3.1升级Log4j1到Log4j2启动时StackOverflowError问题分析与解决
问题场景
运行在Mule-3.3.1上的应用,原使用Log4j 1版本。替换log4j-1*.jar为Log4j2的api、core及桥接包,并配置兼容旧log4j.properties的属性后,应用启动崩溃,抛出java.lang.StackOverflowError。
重复栈跟踪片段
at org.mule.module.launcher.log4j.ApplicationAwareRepositorySelector.getLoggerRepository(ApplicationAwareRepositorySelector.java:62) at org.apache.log4j.LogManager.getLoggerRepository(LogManager.java:171) at org.apache.log4j.Category.<init>(Category.java:177) at org.apache.log4j.Category.<init>(Category.java:192) at org.apache.log4j.Logger.<init>(Logger.java:57) at org.apache.log4j.spi.RootLogger.<init>(RootLogger.java:39) at org.mule.module.launcher.log4j.ApplicationAwareRepositorySelector.getLoggerRepository(ApplicationAwareRepositorySelector.java:62)
原因分析
这是无限递归调用引发的栈溢出:
- Mule的
ApplicationAwareRepositorySelector.getLoggerRepository()方法内部尝试记录日志 - Log4j2桥接包会调用
org.apache.log4j.spi.RepositorySelector.getLoggerRepository()接口方法 - 该接口的实现类恰好是Mule的
ApplicationAwareRepositorySelector,形成循环调用,不断压栈直至超出JVM栈容量
解决方案
- 移除Mule自带的Log4j1相关组件:删除部署包中的
mule-module-launcher-log4j*.jar,或在构建脚本中排除该依赖,避免Mule的日志选择器参与日志初始化流程。 - 自定义无日志依赖的RepositorySelector:实现
org.apache.log4j.spi.RepositorySelector接口,确保getLoggerRepository()方法内部不触发任何日志操作,替换Mule默认的实现类。 - 调整类加载优先级:确保Log4j2桥接包(
log4j-1.2-api.jar)的类加载优先级高于Mule自带的Log4j1类,让桥接包的实现先被加载。 - 适配兼容的Log4j2版本:选择与Mule 3.3.1兼容性更好的Log4j2版本(如2.17.x系列,需注意安全补丁),避免新版本桥接包的特性与旧Mule版本冲突。
内容的提问来源于stack exchange,提问作者Asymptoteles
相关产品推荐
相关产品推荐

