Log4j2自定义TextAreaAppender经ProGuard混淆后无法正常工作
ProGuard混淆后Log4j2自定义TextAreaAppender加载异常问题
应用经ProGuard混淆后,自定义的Log4j2 TextAreaAppender出现加载失败。未混淆的输入Jar运行正常,即使跳过所有类(含依赖)的混淆,错误依然存在。当前使用maven-assembly-plugin生成包含依赖的Jar包。
报错信息
2023-09-28 23:42:58,309 JavaFX Application Thread ERROR Error processing element TextAreaAppender ([Appenders: null]): CLASS_NOT_FOUND 2023-09-28 23:42:58,488 JavaFX Application Thread ERROR Unable to locate appender "JavaFXLogger" for logger config "root"
自定义TextAreaAppender代码
package my.package; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Layout; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.appender.AbstractAppender; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginAttribute; import org.apache.logging.log4j.core.config.plugins.PluginElement; import org.apache.logging.log4j.core.config.plugins.PluginFactory; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import java.io.Serializable; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import javafx.scene.control.CodeArea; @Plugin( name = "TextAreaAppender", category = "Core", elementType = Appender.ELEMENT_TYPE, printObject = true) public final class TextAreaAppender extends AbstractAppender { private static final Logger logger = LogManager.getLogger(); private static CodeArea textArea; private final ReadWriteLock rwLock = new ReentrantReadWriteLock(); private final Lock readLock = rwLock.readLock(); public TextAreaAppender(String name, Filter filter, Layout<? extends Serializable> layout, final boolean ignoreExceptions) { super(name, filter, layout, ignoreExceptions); } @PluginFactory public static TextAreaAppender createAppender( @PluginAttribute("name") String name, @PluginElement("Layout") Layout<? extends Serializable> layout, @PluginElement("Filter") final Filter filter) { if (name == null) { logger.error("No name provided for TextAreaAppender"); return null; } if (layout == null) { layout = PatternLayout.createDefaultLayout(); } return new TextAreaAppender(name, filter, layout, true); } @Override public void append(LogEvent event) { readLock.lock(); // 日志输出逻辑 readLock.unlock(); } }
log4j2.xml配置
<?xml version="1.0" encoding="UTF-8"?> <Configuration packages="my.package" > <!-- Logging Properties --> <Properties> <Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5p | [%thread] (%F:%L) - %m%n</Property> <Property name="LOG_LEVEL">INFO</Property> <Property name="APP_LOG_ROOT">logs</Property> </Properties> <Appenders> <TextAreaAppender name="JavaFXLogger"> <PatternLayout pattern="${LOG_PATTERN}"/> </TextAreaAppender> </Appenders> <Loggers> <Logger name="my" additivity="false" level="${LOG_LEVEL}"> <AppenderRef ref="JavaFXLogger"/> </Logger> <Root level="${LOG_LEVEL}"> <AppenderRef ref="JavaFXLogger"/> </Root> </Loggers> </Configuration>
问题解决方法
Log4j2依赖@Plugin注解识别自定义Appender,ProGuard即便不混淆类名,也可能移除注解信息、优化未直接引用的类/方法,导致Log4j2扫描不到自定义Appender。需添加以下ProGuard规则:
1. 核心ProGuard配置规则
# 保留自定义Appender类及所有成员 -keep class my.package.TextAreaAppender { *; } # 保留注解元数据(Log4j2插件识别必需) -keepattributes *Annotation* -keepattributes Signature -keepattributes SourceFile,LineNumberTable # 保留PluginFactory注解标记的工厂方法 -keepclassmembers class my.package.TextAreaAppender { @org.apache.logging.log4j.core.config.plugins.PluginFactory *; } # 保留Log4j2插件扫描相关类 -keep class org.apache.logging.log4j.core.config.plugins.** { *; }
2. 打包与配置检查
- 确认maven-assembly-plugin打包后,
my.package.TextAreaAppender类存在于Jar中,log4j2.xml配置文件位于Jar的resources目录或根目录。 - 核对log4j2.xml中
packages="my.package"是否准确指向自定义Appender所在包。
3. 验证手段
临时添加ProGuard参数-dontshrink和-dontoptimize,若问题消失,说明是压缩/优化导致的类或注解被移除,需调整keep规则覆盖相关内容。
内容的提问来源于stack exchange,提问作者Ara
相关产品推荐
相关产品推荐

