5

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

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

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

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

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

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

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

编辑:

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

编辑:

我将我的 java 类移动到服务器并在 manifest 属性中使用服务器引用 MainClass,但这并没有解决任何问题。

4

7 回答 7

8
Could not find the main class: MyClass

该错误似乎实际上与您的MANIFEST哪个有关:

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

当您有 jar 时,最好的解决方案是尝试将所需的 jar 包含到清单声明中。

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

请参阅此操作方法

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

如果您的主类位于默认包(未命名的包)中,我不确定加载器是否可以引用它(请参阅此SO 问题
因此将您的主类JarRunner移入包中,并在 <attribute name="Main-Class" value="myPackage.JarRunner"/>元素中适当地声明它。

于 2009-11-25T08:33:20.127 回答
4

在执行 java -jar my-test.jar 之前,您需要在清单文件中指定类路径中所需的所有其他 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,它在这种东西上加载得更好!

于 2009-11-25T09:10:55.057 回答
1

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

于 2009-11-25T08:36:08.590 回答
0

的命令行选项java可以在这里找到。

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

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

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

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

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

于 2009-11-25T09:58:43.417 回答
0

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

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

于 2009-11-25T10:30:53.697 回答
0

这是正在发生的问题,

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

解决方案:-

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

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

这对我有用......希望它也适用于你!

于 2012-09-04T12:29:19.253 回答
0

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

于 2011-12-16T00:02:02.877 回答