OSGi环境下已导入导出仍出现NoClassDefFoundError问题排查
Let's break down your issue and walk through possible causes and fixes. First, here's a recap of your setup:
I'm building a basic VR IDE on Apache Karaf with three Maven projects:
- VRServer: Handles connections to native rendering components
- VR Component Toolkit: Multi-module project containing
VRFrame(which extendsVRComponent) - VRIDE: Manages file I/O and low-level command execution
All bundles are installed in Karaf and show as Active, but starting the VRIDE bundle throws a NoClassDefFoundError for de.e_nexus.vr.tk.VRFrame.
Full Exception Stack Trace
java.lang.NoClassDefFoundError: Lde/e_nexus/vr/tk/VRFrame; at java.lang.Class.getDeclaredFields0(Native Method) ~[?:1.8.0_232] at java.lang.Class.privateGetDeclaredFields(Class.java:2611) ~[?:1.8.0_232] at java.lang.Class.getDeclaredFields(Class.java:1944) ~[?:1.8.0_232] at org.apache.aries.cdi.container.internal.util.Reflection.allFields(Reflection.java:47) ~[!/:1.1.3] at org.apache.aries.cdi.container.internal.annotated.AnnotatedTypeImpl.<init>(AnnotatedTypeImpl.java:42) ~[!/:1.1.3] at org.apache.aries.cdi.container.internal.container.Discovery.lambda$discover$8(Discovery.java:133) ~[!/:1.1.3] at java.util.HashMap$Values.forEach(HashMap.java:981) ~[?:1.8.0_232] at org.apache.aries.cdi.container.internal.container.Discovery.discover(Discovery.java:130) ~[!/:1.1.3] at org.apache.aries.cdi.container.internal.container.ContainerState.<init>(ContainerState.java:178) ~[!/:1.1.3] at org.apache.aries.cdi.container.internal.Activator.doCreateExtension(Activator.java:209) [!/:1.1.3] at org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:242) [!/:1.1.3] at org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:227) [!/:1.1.3] at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:488) [osgi.core-7.0.0.jar:?] at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:420) [osgi.core-7.0.0.jar:?] at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232) [osgi.core-7.0.0.jar:?] at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:450) [osgi.core-7.0.0.jar:?] at org.apache.felix.framework.EventDispatcher.invokeBundleListenerCallback(EventDispatcher.java:915) [org.apache.felix.framework-6.0.3.jar:?] at org.apache.felix.framework.EventDispatcher.fireEventImmediately(EventDispatcher.java:834) [org.apache.felix.framework-6.0.3.jar:?] at org.apache.felix.framework.EventDispatcher.fireBundleEvent(EventDispatcher.java:516) [org.apache.felix.framework-6.0.3.jar:?] at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4817) [org.apache.felix.framework-6.0.3.jar:?] at org.apache.felix.framework.Felix.startBundle(Felix.java:2336) [org.apache.felix.framework-6.0.3.jar:?] at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998) [org.apache.felix.framework-6.0.3.jar:?] at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1260) [!/:3.6.8] at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1233) [!/:3.6.8] at org.apache.felix.fileinstall.internal.DirectoryWatcher.doProcess(DirectoryWatcher.java:520) [!/:3.6.8] at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:365) [!/:3.6.8] at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:316) [!/:3.6.8] Caused by: java.lang.ClassNotFoundException: de.e_nexus.vr.tk.VRFrame not found by de.e-nexus.component [87] at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1597) ~[?:?] at org.apache.felix.framework.BundleWiringImpl.access$300(BundleWiringImpl.java:79) ~[?:?] at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1982) ~[?:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_232] at org.apache.felix.framework.BundleWiringImpl.getClassByDelegation(BundleWiringImpl.java:1375) ~[?:?] at org.apache.felix.framework.BundleWiringImpl.searchImports(BundleWiringImpl.java:1618) ~[?:?] at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1548) ~[?:?] at org.apache.felix.framework.BundleWiringImpl.access$300(BundleWiringImpl.java:79) ~[?:?] at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1982) ~[?:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_232] ... 27 more
Relevant StartIDE Code
package de.e_nexus.desktop.vr.ide; import java.util.logging.Logger; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import org.osgi.service.cdi.annotations.Reference; import org.osgi.service.cdi.annotations.Service; import de.e_nexus.vr.server.ClientKeyboardScancode; import de.e_nexus.vr.server.VRClientHelmetAndControllerListener; import de.e_nexus.vr.server.VRClientKeyboardListener; import de.e_nexus.vr.server.VRServer; import de.e_nexus.vr.server.listeners.VRClientRequestAppInfo; import de.e_nexus.vr.server.listeners.VRClientStatusListener; import de.e_nexus.vr.server.listeners.interaction.HelmetAndControllerInfo; import de.e_nexus.vr.server.osgi.inter.VRServerService; import de.e_nexus.vr.tk.VRFrame; @ApplicationScoped @Service public class StartIDE implements VRClientStatusListener, VRClientRequestAppInfo, VRClientHelmetAndControllerListener, VRClientKeyboardListener { private static final Logger LOG = Logger.getLogger(StartIDE.class.getCanonicalName()); private final static Object lock = new Object(); private VRServer vrServer; public void notifyStatus(boolean connected) { if (!connected) { synchronized (lock) { lock.notify(); } } } @Reference @Inject private VRServerService vrServerService; private VRFrame applicationFrame; @PostConstruct public void initialize() { LOG.fine("Starting VR IDE"); vrServer = vrServerService.getVRServer(); applicationFrame = new VRFrame(vrServer, "test"); LOG.info(getLatin1Title() + " started successfully!"); } @PreDestroy public void teardown() { applicationFrame.remove(); LOG.info("Stoped " + getLatin1Title() + " successfully!"); vrServer = null; } public VRServer getVrServer() { return vrServer; } @Override public void notify(HelmetAndControllerInfo haci) { } @Override public String getLatin1Title() { return "VR IDE"; } @Override public void notifyKeyboardEvent(ClientKeyboardScancode[] downs, ClientKeyboardScancode[] ups, long incomingTime) { System.out.println("me"); } }
Root Cause Analysis & Fixes
The key line in the stack trace is:
Caused by: java.lang.ClassNotFoundException: de.e_nexus.vr.tk.VRFrame not found by de.e-nexus.component [87]
This tells us the VRIDE bundle (id 87, named de.e-nexus.component) can't resolve the VRFrame class from your VR Component Toolkit bundle. Even if you think imports/exports are correct, here are the most likely issues to check:
Verify Export-Package in VR Component Toolkit
- Run
bundle:headers <toolkit-bundle-id>in Karaf shell. Look forExport-Packageand confirmde.e_nexus.vr.tkis listed, with no restrictive version ranges that VRIDE can't match. - Ensure the
VRFrameclass is actually present in the toolkit bundle: runbundle:classes <toolkit-bundle-id> | grep VRFrameto confirm.
- Run
Verify Import-Package in VRIDE
- Run
bundle:headers <vride-bundle-id>and checkImport-Packageforde.e_nexus.vr.tk. If it's missing, your Maven bundle plugin configuration isn't generating the correct import. - Fix your VRIDE's
maven-bundle-pluginconfig to explicitly import the package (or let the plugin auto-generate it correctly):<plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>4.2.1</version> <extensions>true</extensions> <configuration> <instructions> <Import-Package> de.e_nexus.vr.tk, * <!-- Auto-import other required packages --> </Import-Package> <Export-Package>de.e_nexus.desktop.vr.ide</Export-Package> </instructions> </configuration> </plugin>
- Run
Check CDI Container Class Loading Timing
The error happens when Aries CDI scans yourStartIDEclass for fields. Even if bundles are Active, the CDI container might be scanning before the toolkit bundle's classes are fully available.- Try manually starting bundles in order: first start the VR Component Toolkit, then VRServer, then VRIDE.
- Configure startup order in Karaf's
etc/startup.propertiesby adding your toolkit bundle's ID before VRIDE's.
Check Maven Dependencies
Ensure VRIDE'spom.xmlhas a direct dependency on the VR Component Toolkit artifact, with the correct scope (usuallycompileorprovidedif it's an OSGi bundle). This ensures the Maven bundle plugin detects the required import.Test with Minimal Code
Temporarily comment out theVRFramefield and all code referencing it inStartIDE. If VRIDE starts successfully, the issue is definitely related to resolving that class, confirming the import/export issue.
内容的提问来源于stack exchange,提问作者Grim

