我正在使用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。&lt; clinit&gt;(TServerSocket.java:36) 在MyClass.start(未知来源) 在MyClass.main(未知来源)
修改
如果我注释掉实例化缺失类但保留导入的代码,则代码执行正常。
修改
我将我的java类移动到服务器并使用manifest属性中的服务器引用了MainClass,但是没有修复任何内容。
答案 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
请参阅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相同的位置并再次尝试。
答案 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”。
<强>解决方案: - 强>
打开终端,为你的jar提供正确的路径并使用此命令运行它java -jar abc.jar
现在将发生的事情是类加载器将在引用的JARS的正确文件夹中查找,因为现在它们存在于包含您的应用程序JAR的同一文件夹中。现在没有抛出“java.lang.NoClassDefFoundError”异常
这对我有用......希望它对你有用!!!