OSGi应用配置Logback DBAppender时出现ClassNotFoundException问题求助
尝试在OSGi应用中配置DBAppender,但持续遇到以下错误:
10:12:59,285 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - Processing appender named [DB] 10:12:59,285 |-INFO in ch.qos.logback.core.model.processor.AppenderModelHandler - About to instantiate appender of type [ch.qos.logback.classic.db.DBAppender] 10:12:59,285 |-ERROR in ch.qos.logback.core.model.processor.AppenderModelHandler - Could not create an Appender of type [ch.qos.logback.classic.db.DBAppender]. ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type ch.qos.logback.classic.db.DBAppender at ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type ch.qos.logback.classic.db.DBAppender at at ch.qos.logback.core.util.OptionHelper.instantiateByClassNameAndParameter(OptionHelper.java:69) at at ch.qos.logback.core.util.OptionHelper.instantiateByClassName(OptionHelper.java:44) at at ch.qos.logback.core.util.OptionHelper.instantiateByClassName(OptionHelper.java:33) at at ch.qos.logback.core.model.processor.AppenderModelHandler.handle(AppenderModelHandler.java:67) at at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:241) at at ch.qos.logback.core.model.processor.DefaultProcessor.secondPhaseTraverse(DefaultProcessor.java:253) at at ch.qos.logback.core.model.processor.DefaultProcessor.traversalLoop(DefaultProcessor.java:90) at at ch.qos.logback.core.model.processor.DefaultProcessor.process(DefaultProcessor.java:106) at at ch.qos.logback.core.joran.GenericXMLConfigurator.processModel(GenericXMLConfigurator.java:200) at at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:166) at at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:122) at at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:65) at at ch.qos.logback.classic.util.DefaultJoranConfigurator.configureByResource(DefaultJoranConfigurator.java:53) at at ch.qos.logback.classic.util.DefaultJoranConfigurator.configure(DefaultJoranConfigurator.java:34) at at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:98) at at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:77) at at ch.qos.logback.classic.spi.LogbackServiceProvider.initializeLoggerContext(LogbackServiceProvider.java:50) at at ch.qos.logback.classic.spi.LogbackServiceProvider.initialize(LogbackServiceProvider.java:41) at at org.slf4j.LoggerFactory.bind(LoggerFactory.java:183) at at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:170) at at org.slf4j.LoggerFactory.getProvider(LoggerFactory.java:453) at at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:439) at at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:388) at at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:414) at at prodist.robot.equinox.Application.<clinit>(Application.java:37) at at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at at java.lang.Class.newInstance(Class.java:442) at at org.eclipse.equinox.internal.ds.model.ServiceComponent.createInstance(ServiceComponent.java:493) at at org.eclipse.equinox.internal.ds.model.ServiceComponentProp.createInstance(ServiceComponentProp.java:270) at at org.eclipse.equinox.internal.ds.model.ServiceComponentProp.build(ServiceComponentProp.java:331) at at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponent(InstanceProcess.java:620) at at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponents(InstanceProcess.java:197) at at org.eclipse.equinox.internal.ds.Resolver.buildNewlySatisfied(Resolver.java:473) at at org.eclipse.equinox.internal.ds.Resolver.enableComponents(Resolver.java:217) at at org.eclipse.equinox.internal.ds.SCRManager.performWork(SCRManager.java:816) at at org.eclipse.equinox.internal.ds.SCRManager$QueuedJob.dispatch(SCRManager.java:783) at at org.eclipse.equinox.internal.ds.WorkThread.run(WorkThread.java:89) at at org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor.run(Executor.java:70) Caused by: java.lang.ClassNotFoundException: ch.qos.logback.classic.db.DBAppender cannot be found by ch.qos.logback.classic_1.3.5 at at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:461) at at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:372) at at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:364) at at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:161) at at java.lang.ClassLoader.loadClass(ClassLoader.java:352) at at ch.qos.logback.core.util.OptionHelper.instantiateByClassNameAndParameter(OptionHelper.java:56) at ... 40 common frames omitted
我实现了一个Gradle模块osgi-log专门处理日志,其配置如下:
group 'project' version '1.0.0' dependencies { api group: 'org.slf4j', name: 'slf4j-api', version: '2.0.5' implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.3.5' implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.3.5' implementation group: 'ch.qos.logback.db', name: 'logback-classic-db', version: '1.2.11.1' implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.33' implementation group: 'org.ow2.asm', name: 'asm', version: '5.2' implementation group: 'org.ow2.asm', name: 'asm-commons', version: '5.2' implementation group: 'org.ow2.asm', name: 'asm-util', version: '5.2' implementation group: 'org.apache.aries.spifly', name: 'org.apache.aries.spifly.dynamic.bundle', version: '1.3.5' }
其他bundle通过如下依赖使用日志功能:
dependencies { implementation group: 'project', name: 'osgi-log' }
补充说明:本地环境操作,应用和数据库均运行在localhost,使用mysql v.8.0.33。
logback配置如下:
<appender name="DB" class="ch.qos.logback.classic.db.DBAppender"> <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource"> <driverClass>com.mysql.jdbc.Driver</driverClass> <url>jdbc:mysql://127.0.0.1:3306/osgi_app</url> <user>osgi_app</user> <password>osgi_app</password> </connectionSource> </appender>
无法理解为什么BundleLoader找不到DBAppender类,本人对OSGi、bundle以及基于slf4j的logback-classic环境并不完全了解。
1. 修复版本不匹配问题
你使用的logback-classic是1.3.5版本,但logback-classic-db是1.2.11.1版本,两者版本不一致。Logback 1.3.x版本对DBAppender的包结构、依赖逻辑做了调整,低版本的logback-classic-db无法被高版本的logback-classic正确识别加载。
修改Gradle依赖:将logback-classic-db版本升级到与logback-classic、logback-core一致的1.3.5:
implementation group: 'ch.qos.logback', name: 'logback-classic-db', version: '1.3.5'
2. 解决OSGi类可见性限制
OSGi环境中,bundle之间的类访问受严格限制。当前logback-classic bundle尝试加载DBAppender,但logback-classic-db的类未被导出,或者logback-classic未导入对应的包。
修复方式:
- 使用Gradle的OSGi插件(如
biz.aQute.bnd.gradle)生成正确的bundle元数据,确保osgi-log模块导出ch.qos.logback.classic.db包,同时让logback-classic导入该包。 - 若使用bnd插件,可在
bnd.bnd文件中添加:
Import-Package: ch.qos.logback.classic.db, * Export-Package: ch.qos.logback.classic.db, *
3. 调整MySQL驱动类
MySQL 8.0+的官方驱动类已更新为com.mysql.cj.jdbc.Driver,你配置的旧类名com.mysql.jdbc.Driver虽兼容,但可能引发潜在类加载问题,建议修改logback配置:
<driverClass>com.mysql.cj.jdbc.Driver</driverClass>
总结
优先解决版本不匹配问题,这是导致当前错误的核心原因。之后检查OSGi bundle的元数据配置,确保类可见性符合要求,最后更新MySQL驱动类名以适配新版本。
内容的提问来源于stack exchange,提问作者skrenato

