在Eclipse RCP应用中配置System.Logger适配Log4j2的问题
你的问题核心是OSGi的类隔离机制导致Java 21的System.Logger无法自动发现log4j-jpl的实现——普通Java项目靠类路径下的META-INF/services就能加载服务,但RCP的Bundle上下文会阻断这种全局服务发现。以下是具体解决步骤:
1. 正确配置库插件的MANIFEST.MF
库插件作为所有依赖的聚合体,需要确保log4j-jpl的类和服务声明能被其他Bundle访问:
- 添加Bundle类路径:将log4j-jpl的Jar包加入
Bundle-ClassPath,比如:Bundle-ClassPath: ., lib/log4j-api-2.20.0.jar, lib/log4j-core-2.20.0.jar, lib/log4j-jpl-2.20.0.jar - 导出log4j-jpl的包:让其他Bundle能访问到LoggerFinder实现类:
Export-Package: org.apache.logging.log4j.jpl;version="2.20.0" - 声明服务能力:在MANIFEST.MF中添加
Provide-Capability,告诉OSGi这是System.LoggerFinder的实现,并且设置高优先级覆盖默认JUL实现:Provide-Capability: osgi.service;objectClass="java.lang.System$LoggerFinder";service.ranking:Integer=100
2. 强制注册LoggerFinder服务(备选方案)
如果通过Provide-Capability无法自动注册服务,可以手动在库插件的Bundle Activator中注册:
import org.apache.logging.log4j.jpl.Log4jLoggerFinder; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import java.lang.System.LoggerFinder; public class Log4jBundleActivator implements BundleActivator { @Override public void start(BundleContext context) throws Exception { // 注册Log4j的LoggerFinder到OSGi服务注册表 context.registerService(LoggerFinder.class, new Log4jLoggerFinder(), null); } @Override public void stop(BundleContext context) throws Exception { // 无需清理操作 } }
然后在MANIFEST.MF中指定Activator:
Bundle-Activator: com.your.library.plugin.Log4jBundleActivator
3. 配置RCP启动参数(兜底方案)
在RCP的启动配置(Launch Configuration)的VM参数中添加,强制指定System.Logger的实现类:
-Djava.system.logger.finder=org.apache.logging.log4j.jpl.Log4jLoggerFinder
注意:这种方式需要确保org.apache.logging.log4j.jpl.Log4jLoggerFinder类能被系统类加载器访问——如果库插件是普通Bundle,可能需要将log4j-jpl加入RCP的boot classpath(在启动配置的Arguments->VM arguments中添加-Xbootclasspath/a:/path/to/log4j-jpl.jar),但更推荐用前两种OSGi原生的方式。
4. 验证服务注册状态
启动RCP时添加-console参数打开OSGi控制台,输入以下命令检查LoggerFinder服务是否被正确注册:
services java.lang.System$LoggerFinder
如果输出中包含org.apache.logging.log4j.jpl.Log4jLoggerFinder,说明服务注册成功;如果只有默认的JUL实现,说明前面的配置有遗漏。
关键注意事项
- 确保log4j-api、log4j-core等核心依赖也被正确打包到库插件,并且其他Bundle能通过库插件间接访问这些类。
- 避免在多个Bundle中重复打包log4j相关Jar,否则会出现类加载冲突。
- 如果你的库插件是通过Tycho构建的,要确保Maven依赖被正确转换为OSGi Bundle的类路径和导出包配置。
内容的提问来源于stack exchange,提问作者Dralnar

