What is NoClassDefFoundError?

A very common question for new users of OSGi is as follows:

“My bundle throws a NoClassDefFoundError on ‘org.example.FooBar’ even though FooBar is on the classpath. What’s going on??”

In OSGi, it doesn’t even make sense to say that something is “on the classpath” because there is no global classpath in OSGi. Instead, each bundle has its own isolated class loader. The loader inside each bundle can only load classes that are either inside the bundle, or explicitly imported from another bundle.

The preferred way to import from other bundles is to use Import-Package. You must import every package used by your bundle, with the exception of packages that are already part of your bundle and packages that begin with “java.” (for example java.net, java.util etc… these packages are treated specially by the JRE).

If this sounds like a lot of work, don’t worry! Many developers use Bnd to build their bundles, or a tool based on it such as Bndtools or Maven Bundle Plugin. All of these tools automatically generate the Import-Package header for your bundle, by inspecting all of the dependencies in your class files.

Note that if your bundle imports a package, there must be another bundle installed in the OSGi Framework that exports the same package using the Export-Package header. At runtime the Framework matches each import with a corresponding export. If it can’t find a matching export then your bundle will fail to resolve. This happens early in the lifecycle of a bundle, before any code is loaded, so as long as your imports are correct then you should never see errors like ClassNotFoundException or NoClassDefFoundError.

Differences between ClassNotFoundException and NoClassDefFoundError

Both the ClassNotFoundException and NoClassDefFoundError may be seen when using Java libraries that try and load classes reflectively. This typically involves a Java library using Class.forName to load a class.

ClassNotFoundException

A ClassNotFoundException is generated by a call to Class.forName() with a String that contains a class not available on the bundle’s class path. Unless the bundle has a Import-Package or Require-Bundle for the package in question (or a DynamicImport-Package), the runtime will not be able to find the appropriate .class.

NoClassDefFoundError

A NoClassDefFoundError is generated when a class has been found, but one of its dependencies (typically, that involved in a static initialiser block) cannot be. For example, if class A refers to B, and B refers to C, then a client looking up A may work, but B (or C) could be missing. This would generate the error message NoClassDefFoundError: A.