|
| 1 | +--- |
| 2 | +title: What is NoClassDefFoundError? |
| 3 | +summary: Explains the consequences of the class loading architecture |
| 4 | +--- |
| 5 | + |
| 6 | +A very common question for new users of OSGi is as follows: |
| 7 | + |
| 8 | +> “My bundle throws a NoClassDefFoundError on 'org.example.FooBar' even |
| 9 | +> though FooBar is on the classpath. What's going on??” |
| 10 | +
|
| 11 | +In OSGi, it doesn't even make sense to say that something is “on the |
| 12 | +classpath” because **there is no global classpath in OSGi**. Instead, |
| 13 | +each bundle has its own isolated class loader. The loader inside each |
| 14 | +bundle can *only* load classes that are either inside the bundle, or |
| 15 | +*explicitly imported* from another bundle. |
| 16 | + |
| 17 | +The preferred way to import from other bundles is to use |
| 18 | +`Import-Package`. You must import **every** package used by your bundle, |
| 19 | +with the exception of packages that are already part of your bundle and |
| 20 | +packages that begin with “java.” (for example `java.net`, `java.util` |
| 21 | +etc... these packages are treated specially by the JRE). |
| 22 | + |
| 23 | +If this sounds like a lot of work, don't worry! Many developers use |
| 24 | +[Bnd] to build their bundles, or a tool based on it such as [Bndtools] |
| 25 | +or [Maven Bundle Plugin]. All of these tools automatically generate the |
| 26 | +`Import-Package` header for your bundle, by inspecting all of the |
| 27 | +dependencies in your class files. |
| 28 | + |
| 29 | +Note that if your bundle imports a package, there must be another bundle |
| 30 | +installed in the OSGi Framework that exports the same package using the |
| 31 | +`Export-Package` header. At runtime the Framework matches each import |
| 32 | +with a corresponding export. If it can't find a matching export then |
| 33 | +your bundle will fail to resolve. This happens early in the lifecycle of |
| 34 | +a bundle, before any code is loaded, so as long as your imports are |
| 35 | +correct then you should never see errors like ClassNotFoundException or |
| 36 | +NoClassDefFoundError. |
| 37 | + |
| 38 | +### Differences between ClassNotFoundException and NoClassDefFoundError |
| 39 | + |
| 40 | +Both the `ClassNotFoundException` and `NoClassDefFoundError` may be seen |
| 41 | +when using Java libraries that try and load classes reflectively. This |
| 42 | +typically involves a Java library using `Class.forName` to load a class. |
| 43 | + |
| 44 | +#### ClassNotFoundException |
| 45 | + |
| 46 | +A `ClassNotFoundException` is generated by a call to `Class.forName()` |
| 47 | +with a `String` that contains a class not available on the bundle's |
| 48 | +class path. Unless the bundle has a |
| 49 | +[Import-Package](Import-Package "wikilink") or |
| 50 | +[Require-Bundle](Require-Bundle "wikilink") for the package in question |
| 51 | +(or a [DynamicImport-Package](DynamicImport-Package "wikilink")), the |
| 52 | +runtime will not be able to find the appropriate `.class`. |
| 53 | + |
| 54 | +#### NoClassDefFoundError |
| 55 | + |
| 56 | +A `NoClassDefFoundError` is generated when a class has been found, but |
| 57 | +one of its dependencies (typically, that involved in a static |
| 58 | +initialiser block) cannot be. For example, if class `A` refers to `B`, |
| 59 | +and `B` refers to `C`, then a client looking up A may work, but B (or C) |
| 60 | +could be missing. This would generate the error message |
| 61 | +`NoClassDefFoundError: A`. |
| 62 | + |
| 63 | +[Bndtools]: http://bndtools.org |
| 64 | +[Maven Bundle Plugin]: http://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html |
| 65 | +[Bnd]: http://bnd.bndtools.org |
0 commit comments