This post originated from an RSS feed registered with Agile Buzz
by Dominik Wei-Fieg.
Original Post: My favorite eclipse classloading annoyance is fixed!
Feed Title: Ars Subtilior
Feed URL: http://typo.ars-subtilior.com/articles.rss
Feed Description: Finest Handmade Code
Random thoughts about agile software development as an art
Yesterday evening I have spent about two hours helping an intern on an Eclipse problem.
Eclipse (3.0, actually IBM RSM 6) reported a NoClassDefFoundError for a class from one of the plug-ins.
I know that Error, I have had it before, and I dread it. Because this NoClassDefFoundError is a hoax! I got this error when the start method of the Bundle Activator would throw a NullPointerException when it was called because a class of that plug-in was requested. And yesterday evening it turned out to be a ClassNotFoundException for a class which was reported as a NoClassDefFoundError for the same class. The reason the class was not found was that the jar file containing the class was referenced under the wrong name in the manifest. Such things can happen. But throwing a NoClassDefFoundError instead of a ClassNotFoundException doesn’t make it easier to find the cause for the exception.
Today I took a look at the code (org.eclipse.osgi.framework.internal.core.BundleLoader.java) and found that there have been recent changes to it. Before, the findLocalClass method would try to call findLocalClass on the ClassLoader and return the class. It would also catch an ClassNotFoundException and return null. It wouldn’t log the exception or anything, just return null as if nothing exceptional had happend.
Now, the classloading mechanisms in OSGi are complex and the ClassNotFoundException can actually happen without causing a lot of trouble, because other classloading mechanisms will be called after “findLocalClass”.
The version currently checked into eclipse’s cvs repository will not only catch the ClassNotFoundException, it will also rethrow it. But only if it is a special TerminatingClassNotFoundException, a subclass which is constructed when the plug-in could not be activated which contains the actual exception as cause. This is great, because will can now see if the there actually was a NoClassDefFoundError or if the plug-in startup failed due to some other exception.
Still, I would really love to have anther patch in that code:
All ClassNotFoundExceptions which are not TerminatingClassNotFoundException should at least be logged. That way you could easily check the debug output without resorting to finding a log message “BundleLoader[BUNDLENAME].findLocalClass(CLASSNAME)” not followed by a “BundleLoader[BUNDLENAME] found local class CLASSNAME” but rather just look for the message telling you that the bundle you expected to find the class did not find it. So every time you get a NoClassDefFoundError, you could just swtich on the DEBUG logs and grep for the culprit class.
OK, it’s not much of an improvement, now that we have TerminatingClassNotFoundException, before this new excpetion I would have given, hmm, some money (not too much, though) for having that log message in there!
I have filed an feature request with an attached patch at eclipse.org ( 176828 ).