10/01/2009

Resolve NoClassDefFoundException: Find a given JAVA class in JARs

NoClassDefFoundException occures when the classloader was not able to load a class, possibly because of multiple versions present in the classpath (contrary to what we would think at first, it does not actually mean the class was not found - since that would be a ClassNotFoundException).

To find the JAR files containing the conflicting versions, we have to iterate over every JAR file in a given directory, to look for the one which file contains the given class.

So let's assume we have a NoClassDefFoundException: org.jboss.remoting.marshal.Marshaller. This means, we have to find all the JAR files containing this class to look for the duplicates; and then decide which one to get rid of. In a web-application, the application libraries are in WEB-INF/lib, so we should start looking there. The other libraries' placement depends on the platform and the Servlet Container; for example on Ubuntu 9.04/Tomcat 6.0, the system libraries are at /usr/share/tomcat6/lib and the common libraries are at /var/lib/tomcat6/common/lib. These folders should be checked for duplicates as well.

On Solaris, the following script lists all JARs, spitting a line when the class is found:
cd webapps/ROOT/WEB-INF/lib
find . -name "*.jar" -print -exec jar tf {} \; | /usr/xpg4/bin/grep -e '.jar' -e 'org/jboss/remoting/marshal/Marshaller'
The -print parameter prints out the JAR filename, and grep prints either the JAR filename or the classname if found (we have two conditions in grep: either print the JAR name, or the match found).

On Mac OSX, the following is the equivalent:
cd webapps/ROOT/WEB-INF/lib
find . -name "*.jar" -print -exec jar tf {} \; | grep -e '.jar' -e 'org/jboss/remoting/marshal/Marshaller'

In Windows it is not so easy, having a more limited command-line. UnxUtils (download it from http://sourceforge.net/projects/unxutils/files/unxutils/current/UnxUtils.zip/download) can help: after installing, and changing our PATH to include its usr\local\wbin folder:
cd webapps\ROOT\WEB-INF\lib
find . -name "*.jar" -print -exec jar tf {} ; | grep -e "\.jar\|org/jboss/remoting/marshal/Marshaller"

No comments:

Post a Comment