运行java -jar时的java.lang.ClassNotFoundException

时间:2009-11-25 08:29:27

标签: java ant build.xml

我正在使用ant来构建我的build.xml文件,它编译正常,但在通过“java.lang.NoClassDefFoundError”运行生成的jar时获得运行时java -jar my_jar.jar。这似乎出现了很多,但没有一个相关问题的解决方案对我有用。

javac的我的类路径只包含“/usr/local/lib/libthrift.jar”,主.java文件导入了一堆诸如org.apache.thrift.transport.TTransportException之类的thrift包。

当我尝试通过以下方式运行程序时:

java -jar MyClass.jar

,我收到错误:

Exception in thread "main" **java.lang.NoClassDefFoundError**: org/apache/thrift/transport/TTransportException
Caused by: java.lang.ClassNotFoundException: org.apache.thrift.transport.TTransportException
        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:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
Could not find the main class: **MyClass**. Program will exit.

以下是我迄今为止尝试过的不起作用的事情:

  • 在命令行中添加一个标记,如“java -cp /usr/local/lib/libthrift.jar -jar my_jar.jar”,结果与上面的错误相同

  • 在我的jar <attribute name="Class-Path" value="./:/usr/local/lib/libthrift.jar"/>标记中添加 manifest> ,结果与上面的错误相同

  • -Xbootclasspath/a:/usr/local/lib/libthrift.jar:./ 添加到java命令行。它解决了第一个错误,但出现了不同的错误:

    线程“main”中的异常java.lang.NoClassDefFoundError:org / apache / log4j / Logger         在org.apache.thrift.transport.TServerSocket。< clinit>(TServerSocket.java:36)         在MyClass.start(未知来源)         在MyClass.main(未知来源)

修改

如果我注释掉实例化缺失类但保留导入的代码,则代码执行正常。

修改

我将我的java类移动到服务器并使用manifest属性中的服务器引用了MainClass,但是没有修复任何内容。

7 个答案:

答案 0 :(得分:8)

Could not find the main class: MyClass

该错误实际上与您的MANIFEST有关:

  • 可能没有完整的类路径Class-Path:请参阅this HowTo
  

当你有一个jar时,最好的解决方案是尝试将所需的jar包含在manifest声明中。

Manifest-Version: 1.0 
Class-Path:  
 customer_client.jar  
 mailer_client.jar  
 signon_client.jar 
  • 或者可能没有充分定义'my_jar.jar'中的MainClass。

请参阅this HowTo

<target name="jar" depends="compile">
     <delete file="hello.jar"/>
     <delete file="MANIFEST.MF"/>
     <manifest file="MANIFEST.MF">
        <attribute name="Built-By" value="${user.name}"/>
        <attribute name="Main-Class" value="howto.Hello"/>
    </manifest>

      <jar destfile="hello.jar"
           basedir="."
           includes="**/*.class"
           manifest="MANIFEST.MF"
           />
  </target>

<attribute name="Main-Class" value="howto.Hello"/>需要指定MainClass的完整路径(包),而不只是MainClass

如果您的主类位于默认包(unnamed package)中,我不确定加载程序是否可以引用它(请参阅此SO question
因此,将JarRunner移到包中,并在<attribute name="Main-Class" value="myPackage.JarRunner"/>元素中正确声明它。

答案 1 :(得分:4)

您需要在清单文件中指定类路径中所需的所有其他jar,然后才能执行java -jar my-test.jar,这里是我的一个清单文件的副本。通过清单中的所有这些条目,我可以指定java -jar db_field_cleaner.jar,并将所有其他jar内联到类路径中:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: James B
Build-Jdk: 1.6.0_01
Package: com.blah.dbfieldcleaner
Specification-Title: db_field_cleaner
Specification-Version: 2.5.7-SNAPSHOT
Implementation-Title: db_field_cleaner
Implementation-Version: 2.5.7-SNAPSHOT
Implementation-Vendor-Id: com.blah.dbfieldcleaner
Implementation-Vendor:
Main-Class: com.blah.dbfieldcleaner.main.Main
mode: development
url: ..\..\db_field_cleaner\target\site
Class-Path: log4j-1.2.14.jar cygna_commons-2.5.7-SNAPSHOT.jar mail-1.4
 .jar activation-1.1.jar jdic-0.9.5.jar jdic_native-0.9.5.jar jdic_plu
 s-0.2.2.jar jdic_plus_native-0.2.2.jar jtds-1.2.2.jar xstream-1.3.1.j
 ar xpp3_min-1.1.4c.jar commons-net-2.0.jar text_processing-2.5.7-SNAP
 SHOT.jar

或者,使用Maven,它可以更好地加载这种东西!

答案 2 :(得分:1)

您自己给出了答案:-)将所有jar添加到运行时类路径中。如前所述* .jar解决了一个问题,但记录器无法找到,因此将log4j.jar添加到路径中。基本上,这个想法是添加运行到类路径所需的所有jar。

答案 3 :(得分:0)

可以找到java的命令行选项here

-jar-cp/-classpath选项是互斥的。 -jar选项需要使用清单,并且应在此文件中列出依赖关系的相对路径。但实质上,清单是一种可选机制 - 您可以在引导时从外部指定所需信息。如果清单导致您出现问题,请不要使用清单。

我会测试你是否已使用如下命令找到所有依赖项:

java -cp /usr/local/lib/libthrift.jar:my_jar.jar  MyClass

请注意,即使运行时可能需要的所有类都不存在,编译器也可能成功编译您的类。如果存在类的直接依赖性,编译将成功。创建二进制文件不需要依赖项的依赖项,编译器也不会不必要地检查它们。

关于org/apache/log4j/Logger的消息表明您对log4j缺少依赖关系。有必要将此库添加到类路径中。检查Thrift库的文档以确定其依赖性。

答案 4 :(得分:0)

清单文件中的类路径引用是相对引用。只是为了调试,您可能希望将所有罐子复制到与my_jar.jar相同的位置并再次尝试。

参考: http://www.rgagnon.com/javadetails/java-0587.html

答案 5 :(得分:0)

您可以尝试将jar添加到服务器的域中。我遇到了类似的问题,当我在glassfish上运行时,这对我有用。我会得到那些未找到的例外。 Eclipse认识到它并且编译得很好,但是当在服务器上运行时它无法找到该文件。尝试将其添加到服务器安装到的任何lib目录中。

答案 6 :(得分:0)

这是正在发生的问题,

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

<强>解决方案: -

  1. 右键单击项目,选择导出。
  2. 选择Java文件夹,然后在其中选择Runnable JAR File而不是JAR文件。
  3. 选择正确的选项,然后在“库处理”部分中选择第3个选项,即(将所需的库复制到生成的JAR旁边的子文件夹中)。
  4. 单击“完成”,将在指定位置创建JAR以及包含清单文件中提到的JARS的文件夹。
  5. 打开终端,为你的jar提供正确的路径并使用此命令运行它java -jar abc.jar

    现在将发生的事情是类加载器将在引用的JARS的正确文件夹中查找,因为现在它们存在于包含您的应用程序JAR的同一文件夹中。现在没有抛出“java.lang.NoClassDefFoundError”异常

  6. 这对我有用......希望它对你有用!!!