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!
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.
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.
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.
You can omit the -jar
option and start the jar file like this:
java -cp MyJar.jar;C:\externalJars\* mainpackage.MyMainClass
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With