代码之家  ›  专栏  ›  技术社区  ›  Ogre Psalm33

试图用java.exe-jar运行我的jar时出现noclasdeffoundError…怎么了?

  •  55
  • Ogre Psalm33  · 技术社区  · 16 年前

    我有一个应用程序,我正试图将它包装到一个jar中,以便更容易地部署。当作为从类路径可访问的一组类运行时,应用程序编译并运行良好(在Windows命令窗口中)。但是,当我在同一个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日志记录具有logFactory类。最后,我的罐子清单的内容是:

    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,它可以从我的开发窗口框复制到Linux服务器(具有任何依赖JAR),并用于填充数据库(这样,在开发和部署环境中类路径可能会有所不同)。任何有关这个秘密的线索都会受到极大的赞赏!

    6 回复  |  直到 9 年前
        1
  •  55
  •   Community Mr_and_Mrs_D    7 年前

    -jar选项与-classpath互斥。查看旧描述 here

    罐子

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

    有关JAR文件和JAR文件清单的信息,请参阅JAVA工具参考页和Java教程的JAR TRAIL。

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

    一个快速而肮脏的黑客方法是将类路径附加到引导程序类路径:

    -xbootclasspath/a(Xbootclasspath/A): 路径

    指定一个以冒号分隔的directires、jar存档和zip存档路径,以附加到默认的引导程序类路径。

    然而,作为 @Dan 正确地说,正确的解决方案是确保JAR清单包含它将需要的所有JAR的类路径。

        2
  •  28
  •   Jonik    13 年前

    你可以省略 -jar 选项并按如下方式启动JAR文件:

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

        3
  •  15
  •   Gautam Mandsorwale    9 年前

    这就是正在发生的问题,

    如果jar文件是从“C:\java\App\appli.jar”加载的,并且清单文件具有类路径:引用“LIB/Auto.jar”,类加载器将为“其他.jar”查找“C:\java\Apps\LIB”。它不会查看jar文件条目“lib/other.jar”。

    解决方案:

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

    [ 编辑 =3rd选项除了生成JAR之外还生成一个文件夹,2nd选项(“将所需的库打包到生成的JAR中”)也可以使用,因为您有JAR。]

    1. 单击Finish,将在指定位置创建JAR,并在其中创建一个文件夹,其中包含清单文件中提到的JAR。
    2. 打开终端,给您的jar提供正确的路径,并使用这个命令java-jar abcjar运行它。

      现在将发生的是,类装入器将为引用的jar查找正确的文件夹,因为它们现在存在于包含应用程序jar的同一个文件夹中。现在没有抛出“java. Lang.NoCuffeDeFunDror”异常。

    这对我有用…希望对你也有用!!!!

        4
  •  4
  •   flash    16 年前

    如果您在程序中使用外部库,并且试图将它们打包到一个JAR文件中,那么就不那么简单了,因为类路径问题等等。

    我想用 OneJar 对于这个问题。

        5
  •  2
  •   ArtKorchagin Muhammad Naderi    9 年前

    我的罐子也有同样的问题 解决方案

    1. 创建manifest.mf文件:

    清单版本:1.0

    密封:真实

    类路径:lib/jarx1.jar lib/jarx2.jar lib/jarx3.jar

    主类:com.main class

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

    选择导出选中项目的所有输出文件夹

    1. 从工作区选择“使用现有清单”,然后选择manifest.mf文件

    这对我很有用:)

        6
  •  0
  •   Jacob Schoen    12 年前

    当我使用清单时,我发现类路径的jar列表需要在每个jar的列表之后有一个空间,例如“Required_lib/sun/pop3.jar Required_lib/sun/smtp.jar”。即使它是列表中的最后一个。