Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NoClassDefFoundError while trying to run my jar with java.exe -jar...what's wrong?

I have an application that I'm trying to wrap into a jar for easier deployment. The application compiles and runs fine (in a Windows cmd window) when run as a set of classes reachable from the CLASSPATH. But when I jar up my classes and try to run it with java 1.6 in the same cmd window, I start getting exceptions:

C:\dev\myapp\src\common\datagen>C:/apps/jdk1.6.0_07/bin/java.exe -classpath C:\myapp\libs\commons -logging-1.1.jar -server -jar DataGen.jar Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory     at com.example.myapp.fomc.common.datagen.DataGenerationTest.<clinit>(Unknown Source) Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory     at java.net.URLClassLoader$1.run(URLClassLoader.java:200)     at java.security.AccessController.doPrivileged(Native Method)     at java.net.URLClassLoader.findClass(URLClassLoader.java:188)     at java.lang.ClassLoader.loadClass(ClassLoader.java:306)     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)     at java.lang.ClassLoader.loadClass(ClassLoader.java:251)     at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)     ... 1 more 

The funny thing is, the offending LogFactory seems to be in commons-logging-1.1.jar, which is in the class path specified. The jar file (yep, it's really there):

C:\dev\myapp\src\common\datagen>dir C:\myapp\libs\commons-logging-1.1.jar  Volume in drive C is Local Disk  Volume Serial Number is ECCD-A6A7   Directory of C:\myapp\libs  12/11/2007  11:46 AM            52,915 commons-logging-1.1.jar            1 File(s)         52,915 bytes            0 Dir(s)  10,956,947,456 bytes free 

The contents of the commons-logging-1.1.jar file:

C:\dev\myapp\src\common\datagen>jar -tf C:\myapp\libs\commons-logging-1.1.jar META-INF/ META-INF/MANIFEST.MF org/ org/apache/ org/apache/commons/ org/apache/commons/logging/ org/apache/commons/logging/impl/ META-INF/LICENSE.txt META-INF/NOTICE.txt org/apache/commons/logging/Log.class org/apache/commons/logging/LogConfigurationException.class org/apache/commons/logging/LogFactory$1.class org/apache/commons/logging/LogFactory$2.class org/apache/commons/logging/LogFactory$3.class org/apache/commons/logging/LogFactory$4.class org/apache/commons/logging/LogFactory$5.class org/apache/commons/logging/LogFactory.class ... (more classes in commons-logging-1.1 ...) 

Yep, commons-logging has the LogFactory class. And finally, the contents of my jar's manifest:

Manifest-Version: 1.0 Ant-Version: Apache Ant 1.6.5 Created-By: 10.0-b23 (Sun Microsystems Inc.) Main-Class: com.example.myapp.fomc.common.datagen.DataGenerationTest Class-Path: commons-logging-1.1.jar commons-lang.jar antlr.jar toplink  .jar GroboTestingJUnit-1.2.1-core.jar junit.jar 

This has stumped me, and any coworkers I've bugged for more than a day now. Just to cull the answers, for now at least, third party solutions to this are probably out due to licensing restrictions and company policies (e.g.: tools for creating exe's or packaging up jars). The ultimate goal is to create a jar that can be copied from my development Windows box to a Linux server (with any dependent jars) and used to populate a database (so classpaths may wind up being different between development and deployment environments). Any clues to this mystery would be greatly appreciated!

like image 558
Ogre Psalm33 Avatar asked Oct 30 '08 13:10

Ogre Psalm33


People also ask

How do I fix Java Lang NoClassDefFoundError error?

You can fix NoClassDefFoundError error by checking following: Check the exception stack trace to know exactly which class throw the error and which is the class not found by java.

Can we catch NoClassDefFoundError in Java?

In the case of NoClassDefFoundError, the class was present at compile time, but Java runtime could not find it in Java classpath during runtime. As always, the complete code for all examples can be found over on GitHub.


2 Answers

The -jar option is mutually exclusive of -classpath. See an old description here

-jar

Execute a program encapsulated in a JAR file. The first argument is the name of a JAR file instead of a startup class name. In order for this option to work, the manifest of the JAR file must contain a line of the form Main-Class: classname. Here, classname identifies the class having the public static void main(String[] args) method that serves as your application's starting point.

See the Jar tool reference page and the Jar trail of the Java Tutorial for information about working with Jar files and Jar-file manifests.

When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.

A quick and dirty hack is to append your classpath to the bootstrap classpath:

-Xbootclasspath/a:path

Specify a colon-separated path of directires, JAR archives, and ZIP archives to append to the default bootstrap class path.

However, as @Dan rightly says, the correct solution is to ensure your JARs Manifest contains the classpath for all JARs it will need.

like image 107
toolkit Avatar answered Sep 20 '22 12:09

toolkit


You can omit the -jar option and start the jar file like this:

java -cp MyJar.jar;C:\externalJars\* mainpackage.MyMainClass

like image 40
g_tom Avatar answered Sep 20 '22 12:09

g_tom