How to make SkyWalking agent works in OSGI
environment?
OSGI
implements its own set of modularity, which means that each Bundle
has its own unique class loader for isolating different versions of classes.
By default, OSGI runtime uses the boot classloader for the bundle codes, which makes the java.lang.NoClassDefFoundError
exception in the booting stage.
java.lang.NoClassDefFoundError: org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/EnhancedInstance
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:419)
at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:383)
at ch.qos.logback.classic.Logger.log(Logger.java:765)
at org.apache.commons.logging.impl.SLF4JLocationAwareLog.error(SLF4JLocationAwareLog.java:216)
at org.springframework.boot.SpringApplication.reportFailure(SpringApplication.java:771)
at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:748)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)
at by.kolodyuk.osgi.springboot.SpringBootBundleActivator.start(SpringBootBundleActivator.java:21)
at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:849)
at org.apache.felix.framework.Felix.activateBundle(Felix.java:2429)
at org.apache.felix.framework.Felix.startBundle(Felix.java:2335)
at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1566)
at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:297)
at java.base/java.lang.Thread.run(Thread.java:829)
How to resolve this issue?
- we need to set the parent classloader in
OSGI
toAppClassLoader
, through the specific parameterorg.osgi.framework.bundle.parent=app
. The list of parameters can be found in the OSGI API - Load the
SkyWalking
related classes to the bundle parent class loader,AppClassLoader
, with the parameterorg.osgi.framework.bootdelegation=org.apache.skywalking.apm.*
ororg.osgi.framework.bootdelegation=*
. This step is optional. Some OSGi implementations (i.e. Equinox) enable them by default