运行 java -jar 时出现 java.lang.ClassNotFoundException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1795452/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:44:04  来源:igfitidea点击:

java.lang.ClassNotFoundException when running java -jar

javaantbuild.xml

提问by Heinrich Schmetterling

I'm using ant to build my build.xmlfile, it compiles ok, but then getting a runtime java.lang.NoClassDefFoundErrorwhen running the resulting jar via "java -jar my_jar.jar". It seems like this comes up a lot but none of the related questions' solutions worked for me.

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

My classpath for javaccontains only "/usr/local/lib/libthrift.jar" and the main .javafile imports a bunch of thrift packages such as org.apache.thrift.transport.TTransportException.

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

When I try running the program via:

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

java -jar MyClass.jar

, I get the error:

,我收到错误:

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

Here are the things I've tried so far that don't work:

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

  • adding a flag on the command line like "java -cp /usr/local/lib/libthrift.jar-jar my_jar.jar", the result is the same error as above

  • adding <attribute name="Class-Path" value="./:/usr/local/lib/libthrift.jar"/>inside my jar's manifest>tag, the result is the same error as above

  • adding -Xbootclasspath/a:/usr/local/lib/libthrift.jar:./to the java command line. it solves the first error but a different error comes up:

    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger at org.apache.thrift.transport.TServerSocket.<clinit>(TServerSocket.java:36) at MyClass.start(Unknown Source) at MyClass.main(Unknown Source)

  • 在命令行中添加一个类似“java ”的标志,结果是和上面一样的错误-cp /usr/local/lib/libthrift.jar-jar my_jar.jar

  • 添加&lt;attribute name="Class-Path" value="./:/usr/local/lib/libthrift.jar"/>到我的 jarmanifest>标签中,结果与上面的错误相同

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

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

EDIT:

编辑:

If I comment out the code that instantiates the missing classes but leave the imports, the code executes fine.

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

EDIT:

编辑:

I moved my java classes to a server and referenced the MainClass with the server in the manifest attribute, but that didn't fix anything.

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

回答by VonC

Could not find the main class: MyClass

The error seems actually related to your MANIFESTwhich:

该错误似乎实际上与您的以下MANIFEST内容有关:

  • may not have a complete classpath Class-Path: see this HowTo
  • 可能没有完整的类路径Class-Path:请参阅此 HowTo

The best solution when you have a jar is to try to include the required jars into the manifest declaration.

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

Manifest-Version: 1.0 
Class-Path:  
 customer_client.jar  
 mailer_client.jar  
 signon_client.jar 
  • or may not define adequately the MainClass within your 'my_jar.jar'.
  • 或者可能没有在“my_jar.jar”中充分定义 MainClass。

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

the <attribute name="Main-Class" value="howto.Hello"/>needs to specify the full path (packages) of the MainClass, not just MainClass.

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

If your main class is in the default package (the unnamed package), I am not sure it can be referenced by the loader (see this SO question)
So move your JarRunnerinto a package, and declare it appropriately in the <attribute name="Main-Class" value="myPackage.JarRunner"/>element.

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

回答by GustyWind

You had given answer yourself :-) add all the jars to your runtime classpath.As you said earlier *.jar solved one problem but loggers are not able to find out, so add log4j.jar to the path. Basically the idea is add all the jars required for running in to classpath.

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

回答by James B

You need to specify all the other jars that are required in your classpath in the manifest file before you can execute java -jar my-test.jar, here is a copy of one of my manifest files. With all these entries in the manifest I can specify java -jar db_field_cleaner.jarand all the other jars are inlined into the classpath :

您需要在清单文件中指定类路径中所需的所有其他 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

Alternatively, use Maven, it's loads better at this kind of stuff!

或者,使用 Maven,它在这类东西上负载更好!

回答by McDowell

The command line options for javacan be found here.

java可以在此处找到的命令行选项。

The -jarand -cp/-classpathoptions are mutually exclusive. The -jaroption requires the use of a manifest and the relative paths to dependencies should be listed in this file. But essentially, the manifest is an optional mechanism - you can specify the required information externally at bootstrap time. If the manifest is causing you problems, don't use one.

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

I would test that you have you have located all your dependencies with a command like this:

我将测试您是否已使用以下命令找到所有依赖项:

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

Note that the compiler may successfully compile your classes even if all the classes that might be required at runtime are not present. Compilation will succeed if the direct dependencies of your classes are present. The dependencies of your dependencies are not necessary to create the binary and the compiler will not inspect them needlessly.

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

The message about org/apache/log4j/Loggersuggests that you have a missing dependency on log4j. It will be necessary to add this library to the classpath. Check the documentation for the Thrift library to determine its dependencies.

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

回答by aldrin

The class path references in the manifest file are relative refs. Just to debug, you might want to copy all the jars into the same location as my_jar.jar and attempt it again.

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

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

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

回答by Randnum

You might try adding the jars to the domain of the server. I had a similar problem and this worked for me when I was running it on glassfish. I would get those not found exceptions. Eclipse recognized it and it compiled fine but when ran on the server it couldn't find the file. Try adding it to whatever lib directory the server is installed to.

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

回答by Gautam Mandsorwale

This is the problem that is occurring,

这是正在发生的问题,

if the JAR file was loaded from "C:\java\apps\appli.jar", and your manifest file has the Class-Path: reference "lib/other.jar", the class loader will look in "C:\java\apps\lib\" for "other.jar". ?It won't look at the JAR file entry "lib/other.jar".

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

Solution:-

解决方案:-

  1. Right click on project, Select Export.
  2. Select Java Folder and in it select Runnable JAR File instead of JAR file.
  3. Select the proper options and in the Library Handling section select the 3rd option i.e. (Copy required libraries into a sub-folder next to the generated JAR).
  4. Click finish and your JAR is created at the specified position along with a folder that contains the JARS mentioned in the manifest file.
  5. open the terminal,give the proper path to your jar and run it using this command java -jar abc.jar

    Now what will happen is the class loader will look in the correct folder for the referenced JARS since now they are present in the same folder that contains your app JAR..There is no "java.lang.NoClassDefFoundError" exception thrown now.

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

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

This worked for me... Hope it works you too!!!

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