Tuesday, July 21, 2009

SOT: Why JVM's Have No Class (.. or do they?)

So last week I was working with an external jar from ColdFusion and ran into what I thought was your typical ClassNotFoundException. It was perplexing because I knew the jar was accessible to the Classloader. So I could not figure out why the jvm was saying the class could not be found. At the time I was mainly focused on fixing the problem, but something about the exception struck me as odd. Rather than the typical ClassNotFoundException, the error message showed a chained exception that looked something like this:

java.lang.ExceptionInInitializerError
...
...
Caused by: java.lang.NoClassDefFoundError
...
...



With chained exceptions, I have found the first message is often a throw-away error with the true cause being further down the line. So I ignored the initial message and focused on what I thought was a ClassNotFoundException. A great article from the archives of javaworld.com explained why that was a mistake in this case. (Now keep in mind the entry is dated. So not everything in it still applies to later jvm's)

The article explains there are different ways classes can be loaded, each with different implications. When a class is loaded with the Class.forName(..) method, the jvm attempts to initialize the class. That means any static initialization code will be executed as well. If for some reason an error occurs, like during the execution of the static code blocks, the jvm may throw a misleading NoClassDefFoundError. It does necessarily not mean the class cannot be found, rather that it cannot be successfully loaded for some reason.

Perhaps a more elegant and intuitive name for this exception would have been ClassDefinitionLoadError . Oh well. I guess the lesson of the day is, pay attention to those Class exceptions. Sometimes they are tad misleading ;-)

2 comments:

Marc Esher July 24, 2009 at 4:24 AM  

I had a similar experience a few weeks back on a java app I was working on. I was getting strange NoClassDefFoundErrors attempting to load the jTDS jar file. Nothing at all about my classpath had changed, and it had worked previously.

Turned out, it was a bad connectstring in a config file causing the problem:

connecturl=connecturl=jdbc:jtds....

it was just a bad copy/paste job. I spent 10 minutes puzzling over the class path before having the realization you did... it wasn't a missing class, but a failure to correctly load the class due to bad initialization.

+1 for a better error name!

cfSearching July 24, 2009 at 7:50 PM  

@Mark,

Yes, I guess the error makes from the designer's point of view. But from a usage perspective .. not so much.

Nothing like an ambiguous error message to liven up your day ;)

-Leigh

  © Blogger templates The Professional Template by Ourblogtemplates.com 2008

Header image adapted from atomicjeep