简体   繁体   English

Java Jar - 类路径问题

[英]Java Jar - classpath issue

Running out of ideas on the cause of the issue.关于问题原因的想法已经用完了。 I have a java jar (built from gradle under intellij if that matters).我有一个 java jar(如果重要的话,可以在 intellij 下从 gradle 构建)。

  • Jar has a manifest. Jar 有一个清单。

  • Launching java -jar MyJar.jar from directory containing jar gives "could not find or load main class companyname.mainclass"从包含 jar 的目录启动java -jar MyJar.jar给出“找不到或加载主类 companyname.mainclass”

  • Java is reading from manifest as Editing the manifest file inside jar to mainclass2 will change the name in the error message Java 正在从清单中读取,因为将 jar 内的清单文件编辑为mainclass2将更改错误消息中的名称

  • Manifest contains only version on a line, then main class attribute on a line, then 2 blank lines清单仅在一行中包含版本,然后在一行中包含主类属性,然后是 2 个空行

  • All dependencies are in a /lib folder relative to jar so no classpath specified in manifest所有依赖项都在相对于 jar 的 /lib 文件夹中,因此清单中没有指定类路径

  • Opening jar in zip file program shows folder companyname with file in it mainclass so the qualified name is reflected in jar structure.在 zip 文件程序中打开 jar 会显示文件夹companyname和其中的文件mainclass因此限定名称反映在 jar 结构中。 Capitalisation is also correct.大小写也是正确的。

  • Manually specifying class name java -cp MyJar.jar companyname.mainclass gives the same class not found error手动指定类名java -cp MyJar.jar companyname.mainclass给出了相同的类未找到错误

  • The class in question does have a main method, and does run fine under the IDE when unpackaged.有问题的类确实有一个 main 方法,并且在解包时在 IDE 下运行良好。

What am I missing (apart from more and more chunks of hair off my head)?我错过了什么(除了头上越来越多的头发)?

Edit Additional details: - using Java 8编辑其他详细信息: - 使用 Java 8

jar structure:罐子结构:

-META-INF
  MANIFEST.MF
-companyname
  -module
    -interfaces
      interface1.class
    -commands
      baseCommand.class
      register.class
      specialCommand.class
    moduleSpec.class
    moduleProcessor.class
  mainclass.class
log4j.xml
springconfig1.xml
springconfig2.xml

Manifest file:清单文件:

Manifest-Version: 1.0
Main-Class: companyname.mainclass
(newline char here)
(newline char here)

First, make sure you're creating the executable jar correctly.首先,确保您正确创建了可执行 jar。 See this answer for info on creating an executable jar using gradle.有关使用 gradle 创建可执行 jar 的信息,请参阅此答案

If you're creating and packaging your jar correctly, it's possible that it can't load your main class because it has dependencies that cannot be found.如果您正确地创建和打包您的 jar,它可能无法加载您的主类,因为它具有无法找到的依赖项。 You said:你说:

All dependencies are in a /lib folder relative to jar so no classpath specified in manifest所有依赖项都在相对于 jar 的 /lib 文件夹中,因此清单中没有指定类路径

If you mean that the lib folder is in the same folder on the filesystem as the .jar file, then your dependencies won't be found.如果您的意思是lib文件夹与 .jar 文件位于文件系统上的同一文件夹中,那么将找不到您的依赖项。 The contents of that lib folder will not be automatically added to the jar's classpath.该 lib 文件夹的内容不会自动添加到 jar 的类路径中。 You can manually add them to the classpath of the java command, or you can add them to the manifest.您可以手动将它们添加到java命令的类路径中,也可以将它们添加到清单中。 If you add them to the classpath, you can use wildcards:如果将它们添加到类路径,则可以使用通配符:

java -cp "MyJar.jar;lib/*" com.mycompany.MyMainClass

If you add them to the manifest, you can't use wildcards , so you need to specify each individual jar dependency under your lib directory.如果将它们添加到清单中, 则不能使用通配符,因此您需要在 lib 目录下指定每个单独的 jar 依赖项。 (See the Oracle tutorial on adding jars to the classpath for more info.) (有关更多信息,请参阅有关向类路径添加 jarOracle 教程。)

If the lib directory is inside the jar (a "fat jar"), then there's no classpath that will help you: the default classloader will not load dependencies from within the executable jar.如果 lib 目录在 jar 中(一个“fat jar”),那么没有类路径可以帮助您:默认的类加载器不会从可执行 jar 中加载依赖项。 However, there are multiple tools that allow you to create a fat jar that includes all its dependencies, and distribute it as a single executable jar.但是,有多种工具允许您创建一个包含所有依赖项的胖 jar,并将其作为单个可执行 jar 分发。 Since you're using gradle, the gradle shadow plugin may be of use to you.由于您使用的是 gradle,因此gradle shadow 插件可能对您有用。

The manifest will be of use here.清单将在这里使用。 Also, if you try另外,如果你尝试

java -jar -verbose:class MyJar | grep mainclass 

It'll confirm if your class is being loaded.它将确认您的课程是否正在加载。 Oh - Also, are there a mix of JVMs at play here?哦 - 另外,这里有混合使用 JVM 吗?

Ensure java -version shows a Java 8, since that's what you hint that Intellij/Gradle is building with.确保 java -version 显示 Java 8,因为这是您暗示 Intellij/Gradle 正在构建的内容。

原因可能是如果您的主类有一个静态初始化块,它会在运行时引发一些错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM