‘OSGi Demystified’ is a series of articles addressing common OSGi issues in CICS. We offer insight into OSGi, discuss best practices, and provide setup and configuration advice. This is the first in the series of section 2, to see the previous section discussing CICS bundles, Liberty bundles, and OSGi services, follow this link. In this section of articles we’ll address a number of common Java and OSGi class loader problems you might encounter in CICS OSGi and Liberty JVM servers.
- The difference between a
- How to solve
- OSGi dependency resolution and class loading explained.
- Gain performance with stricter OSGi compliance
Whether you are developing a new OSGi application, migrating an existing Java application to OSGi, or simply using third-party components that aren’t playing nicely with OSGi – the chances are you’ll hit a class loading issue and curse CICS for inflicting OSGi upon you.
Once you have finished turning the air blue…take a deep breath and relax. Here at CICS Java HQ, we believe the benefits of OSGi far outweigh the initial learning curve. Whether it’s the mature component model, the power of versioning, the improved class loading performance, the dynamic service architecture, or the install time dependency resolution – there are many reasons why OSGi is a good choice. That said, you are not here because your OSGi journey has been smooth. You have most likely fallen foul of OSGi’s sharp edges and are looking for enlightenment. So let’s get straight to it.
ClassNotFoundExceptions / NoClassDefFoundErrors
Take a careful look at the failure. Did you get a
ClassNotFoundException or did you get a
NoClassDefFoundError? These conditions are easily confused. They mean very different things despite the seemingly common problem of the class failing to load. Let us start with the obvious differences. ClassNotFoundException is an exception, NoClassDefFoundError is an error. You realised that already, but it’s a good way to tell them apart. Be advised there are no other variants of either the exception or the error despite numerous typing errors out on the wild web!
A NoClassDefFoundError is a result of the JVM failing to load a class that was present during compile time. That means the class was available to your development environment; and the application compiled – but for some as yet unknown reason, the class is not available to your runtime.
A ClassNotFoundException on the other hand, is a result of your code (or third-party code) not the JVM, dynamically attempting to load a class and failing. The code has probably used
loadClass() with a textual class name. That class name might have been taken from a properties file, a configuration file, or it was just plain hard-coded. Alas, the compiler didn’t know about this class when your application was compiled. The exception indicates that the class you want to dynamically load is not visible to your OSGi bundle’s class loader.
Let’s begin by analysing the
NoClassDefFoundError. Why did your application fail to load the class if it was found at compile time? We stressed the word load because this error can occur either as a result of the class not being found, or if the class was found yet failed to load. It is quite plausible that something else might have prevented the class from fully loading, perhaps an exception from a static initialiser? Take a good look at the Exception stack trace as the clues to load failures are usually there.
If a class really is not found, and you are in plain Java (non OSGi) it is extremely likely that you omitted a JAR from your application class path. Go find it, add it to the class path and sit on the naughty step for a while.
But we’re dealing with OSGi here…that can’t happen can it? Newsflash. Yes it can. Each bundle has a class path (the Bundle-ClassPath header configured in the MANIFEST.MF of the JAR) and your bundle can contain JARs. So if you are
abusing exploiting OSGi in this way and making it look like a class path application then you should expect all the associated problems of a class path. Remedies include:
• ensuring all the required JARs are deployed within your bundle and listed on the Bundle-ClassPath
• take the dependent JARs, turn them into bundles and deploy them as first class OSGi bundles. Doing so will give you the full power of OSGi’s dependency resolution, versioning, dynamic updates and so on. Don’t forget to update your original bundle with an appropriate Import-Package statement.
By Ivan Hargreaves, Mark Cocker and Abigail Bettle-Shaffer.
For more on OSGi by Invoke Ivan, take a look at this page and keep an eye out for the next section instalments on our Facebook and Twitter pages.
Read the next in series tackling the mystery of OSGi dependencies in Eclipse.