由于无法加载主类错误而无法运行 JAR 文件

Posted

技术标签:

【中文标题】由于无法加载主类错误而无法运行 JAR 文件【英文标题】:Cannot run JAR file due to cannot load main class error 【发布时间】:2021-07-08 03:28:20 【问题描述】:

我使用 Gradle 构建框架构建了我的项目并生成了一个 JAR 文件。但是,在这种情况下,输出 jar 文件无法从主类 (miner.Tracker) 加载主要方法。

正如我所提到的,使用 -jar 选项运行失败。

$ java -jar Backtracker.jar
Error: Could not find or load main class miner.Tracker

我也尝试使用-cp 选项直接运行该类,但失败了。

$ java -cp Backtracker.jar miner.Tracker
Error: Could not find or load main class miner.Tracker

最后,我解压了 jar 文件并从里面调用了这个类。这次成功找到并运行了main方法的类。

$ mkdir classes
$ cd classes
$ classes $ tar xvf ../Backtracker.jar
x META-INF/
x META-INF/MANIFEST.MF
x CHANGELOG.md
x com/
1. ...

classes $ java miner.Tracker
2021-04-12 22:47:48.008 | Logging started
...

这是META-INF/MANIFEST.MF 文件的内容。

Manifest-Version: 1.0
Implementation-Title: BackTracker
Implementation-Version: 1.9.xx
Specification-Title: release
Specification-Version: 1.9.xx
Main-Class: miner.Tracker

我从 Oracle Java 1.8 运行它。

$ java -version
java version "1.8.0_271"
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)

感谢您的帮助。


更新:

$ tar tvf Backtracker.jar |grep miner\/Tracker

-rw-r--r-- 0 0 0  2175 Apr 14 20:38 miner/TrackerUtil.class
-rw-r--r-- 0 0 0 40963 Apr 14 20:38 miner/Tracker.class

【问题讨论】:

你的包名不完整,能发一下你的app的结构吗? 如果你共享jar文件会更容易。 认真的吗?您正在共享所有这些信息并完全省略“...”背后的重要内容,即主类在您的目录结构中的什么位置?恕我直言:这是某种谜题或测验吗?你为什么要让每个人都很难帮助你? @code_mechanic Jar 文件包含数以万计的类文件,目录结构有些复杂。至少我可以分享``` $ tar tvf Backtracker.jar |grep miner\/Tracker -rw-r--r-- 0 0 0 2175 Apr 14 20:38 miner/TrackerUtil.class -rw-r--r -- 0 0 0 40963 Apr 14 20:38 miner/Tracker.class ``` 有没有更好的方法来共享目录结构? “Jar 文件包含数以万计的类文件” 为什么不制作一个简单的测试 jar,其中包含一个仅打印“Hello World”的 miner.Tracker 类?您不认为排除故障会更容易吗? 【参考方案1】:

经过一些实验,我同意用户 11thdimension 的观点,即您的清单文件可能有问题。不过,我不认为这与非数字版本有关。我试过了,它有效。

我注意到的是,如果您添加的行包含的空格多于普通空格(字符 32 dec,20 hex),您将看到您描述的错误,这仅仅是因为无法解析清单。显然,清单解析器在每个非空行上都需要 MyKey: MyValue 之类的东西。即使在末尾以外的任何地方的空行都可能导致相同的问题,如果它们位于所谓的部分的中间。因此,如果您有以下清单之一,无论您使用 -cp 还是 -jar,您都会看到 ClassNotFoundException

Manifest-Version: 1.0
Main-Class: miner.Tracker
x
Manifest-Version: 1.0

Main-Class: miner.Tracker

即使在最后一行之后有一行只包含这样的制表符,也会发生错误:

Manifest-Version: 1.0
Main-Class: miner.Tracker
    

如果您有使用其他不可见字符的行,例如非标准Unicode spaces,也是如此。

就像我在之前的评论中所说的:检查清单中的任何位置是否存在此类字符。如果这没有产生任何结果,请同时检查您的 Java 源代码文件,尤其是包名和类名。


更新:这是一个小 Java 示例,展示了我之前解释过的内容:

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.jar.Manifest;

public class ManifestValidator 
  public static void main(String[] args) 
    // Valid: nothing unusual
    parseManifest("Manifest-Version: 1.0\nMain-Class: miner.Tracker\n");
    // Valid: trailing empty line
    parseManifest("Manifest-Version: 1.0\nMain-Class: miner.Tracker\n\n");
    // Valid: line continuation by leading space
    parseManifest("Manifest-Version: 1.0\nMain-Class: miner.Track\n er\n");
    // Valid: last line is ignored if it does not end with a line feed
    parseManifest("Manifest-Version: 1.0\nMain-Class: miner.Tracker\nSome garbage");

    // Invalid: line beginning with tab
    parseManifest("Manifest-Version: 1.0\nMain-Class: miner.Tracker\n\t\n");
    // Invalid: not a key-value pair "key: value"
    parseManifest("Manifest-Version: 1.0\nMain-Class: miner.Tracker\nFoo=bar\n");
    // Invalid: empty line in section
    parseManifest("Manifest-Version: 1.0\n\nMain-Class: miner.Tracker\n");
    // Invalid: non-default unicode space instead of normal one
    parseManifest("Manifest-Version: 1.0\nMain-Class:\u00A0miner.Tracker\n");
  

  public static void parseManifest(String content) 
    try 
      Manifest manifest = new Manifest(new ByteArrayInputStream(content.getBytes()));
      System.out.println(manifest.getMainAttributes().entrySet());
    
    catch (IOException e) 
      System.out.println(e);
    
  

[Manifest-Version=1.0, Main-Class=miner.Tracker]
[Manifest-Version=1.0, Main-Class=miner.Tracker]
[Manifest-Version=1.0, Main-Class=miner.Tracker]
[Manifest-Version=1.0, Main-Class=miner.Tracker]
java.io.IOException: invalid header field
java.io.IOException: invalid header field
java.io.IOException: invalid manifest format
java.io.IOException: invalid header field

【讨论】:

更新:我添加了一些示例代码,使用相应的 JDK 类解析有效和无效清单。

以上是关于由于无法加载主类错误而无法运行 JAR 文件的主要内容,如果未能解决你的问题,请参考以下文章

java无法找到或加载主类是怎么回事?

java运行显示“找不到或无法加载主类”!

idea打包jar,运行错误: 找不到或无法加载主类

错误: 找不到或无法加载主类 ArrayListMagnet?

运行maven-assembly创建的可执行jar:错误:无法找到或加载主类

运行java文件显示找不到或无法加载主类怎么解决?