NoClassDefFoundError试图使用java.ex-jar运行我的JAR……怎么了?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (76)

我有一个应用程序,我试图将其包装到一个jar中以便于部署。当作为一组可从CLASSPATH访问的类运行时,应用程序编译并运行良好(在Windows cmd窗口中)。但是当我激活我的类并尝试在同一个cmd窗口中使用java 1.6运行它时,我开始发生异常:

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

有趣的是,有问题的LogFactory似乎在commons-logging-1.1.jar中,它位于指定的类路径中。jar文件(是的,它真的存在):

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

commons-logging-1.1.jar文件的内容:

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 ...)

是的,commons-logging具有LogFactory类。最后,我的jar的清单的内容:

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

这一直困扰着我,以及我一直在窃听超过一天的同事。只是为了挑选答案,至少现在,第三方解决方案可能由于许可限制和公司政策(例如:用于创建exe或打包jar的工具)而出现。最终目标是创建一个jar文件,可以从我的开发Windows机器复制到Linux服务器(使用任何依赖jar)并用于填充数据库(因此,classpaths可能在开发和部署环境之间有所不同)。

提问于
用户回答回答于

-jar选项与-classpath互斥。在这里看到一个旧的描述

-罐 执行封装在JAR文件中的程序。第一个参数是JAR文件的名称,而不是启动类名称。为了使这个选项起作用,JAR文件的清单必须包含一个Main-Class:classname形式的行。这里,classname标识具有公共静态void main(String [] args)方法的类,该方法用作应用程序的起点。 有关使用Jar文件和Jar文件清单的信息,请参阅Jar工具参考页和Java Tutorial的Jar trail。 当您使用此选项时,JAR文件是所有用户类的来源,并且其他用户类路径设置将被忽略。

快速而肮脏的破解是将你的类路径追加到引导类路径中:

-Xbootclasspath / a:路径 指定冒号分隔的directires路径,JAR归档文件和ZIP归档文件以追加到默认的引导程序类路径。

正确的解决方案是确保您的JAR Manifest包含所需JAR的类路径。

用户回答回答于

可以省略该-jar选项并像这样启动jar文件:

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

扫码关注云+社区