NoClassDefFoundError尝试运行我的jar与java.exe -jar …有什么不对?

我有一个应用程序,我试图包装成一个jar更容易部署。 当作为一组CLASSPATH可访问的类运行时,应用程序编译并运行良好(在Windows cmd窗口中)。 但是,当我激活我的类,并尝试在同一个CMD窗口中运行它与Java 1.6,我开始得到exception:

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,它在指定的类path中。 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 

这一直困扰着我,还有任何一个同事,我已经听了一天以上。 只是为了挑选答案,至less现在第三方解决scheme可能是由于许可限制和公司政策(例如:创buildexe或打包jar的工具)。 最终的目标是创build一个jar,可以从我的开发Windows机器复制到Linux服务器(具有任何相关的jar),并用于填充数据库(因此classpaths可能在开发和部署环境之间变得不同)。 任何这个神秘的线索将不胜感激!

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

-jar

执行封装在JAR文件中的程序。 第一个参数是JAR文件的名称,而不是启动类名称。 为了使这个选项起作用,JAR文件的清单必须包含一个Main-Class:classnameforms的行。 在这里,classname标识具有公共静态void main(String [] args)方法的类,该方法用作应用程序的起点。

有关使用Jar文件和Jar文件清单的信息,请参阅Jar工具参考页和Java Tutorial的Jar trail。

使用此选项时,JAR文件是所有用户类的来源,而其他用户类path设置将被忽略。

一个快速和肮脏的黑客是将您的类path追加到引导类path:

-Xbootclasspath / a: path

指定一个以冒号分隔的directirespath,JAR归档文件和ZIP归档文件以追加到默认的引导程序类path。

但是,正如@Dan所说的,正确的解决scheme是确保您的JAR Manifest包含所需的所有JAR的类path。

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

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

这是正在发生的问题,

如果JAR文件是从“C:\ java \ apps \ appli.jar”加载的,并且您的清单文件具有Class-Path:reference“lib / other.jar”,则类加载器将在“C:\ java \ apps \ lib \“作为”other.jar“。 它不会查看JAR文件条目“lib / other.jar”。

解:-

  1. 右键单击项目,select导出。
  2. selectJava文件夹,并在其中selectRunnable JAR文件而不是JAR文件。
  3. select适当的选项,并在库处理部分select第三个选项,即(将所需的库复制到生成的JAR旁边的子文件夹中)。

[ 编辑 =第三个选项生成一个文件夹除了jar,第二个选项(“将所需的库包到生成的JAR中”)也可以使用,因为你有jar。 ]

  1. 单击完成,您的JAR将在指定的位置创build,同时包含清单文件中提到的JARS的文件夹。
  2. 打开terminal,给你的jar的正确path,并使用这个命令java -jar abc.jar运行它

    现在会发生什么是类加载器将在正确的文件夹中查找引用的JARS,因为现在它们出现在包含您的应用程序JAR的相同文件夹中。现在没有抛出“java.lang.NoClassDefFoundError”exception。

这对我工作…希望它也适用于你!

如果在程序中使用外部库,并且尝试将所有内容打包在一个jar文件中,并不是那么简单,因为classpath问题等等。

我宁愿使用OneJar来解决这个问题。

我的解决scheme与我的jar有同样的问题

  1. 创buildMANIFEST.MF文件:

Manifest-Version:1.0

密封:真实

类path:。 lib / jarX1.jar lib / jarX2.jar lib / jarX3.jar

主要类:com.MainClass

  1. 右键单击项目,select导出。

select导出所有输出文件夹的检查项目

  1. select使用工作区中的现有清单并selectMANIFEST.MF文件

这对我工作:)

我发现,当我使用的清单,类列表jar的列表需要每个jar后列出一个空格,例如“required_lib / sun / pop3.jar required_lib / sun / smtp.jar”。 即使它是列表中的最后一个。