简体   繁体   English

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

[英]Cannot run JAR file due to cannot load main class error

I built my project and generated a JAR file using Gradle build framework.我构建了我的项目并使用 Gradle 构建框架生成了一个 JAR 文件。 However, the output jar file fails to load the main methods from the main class ( miner.Tracker ) in this case.但是,在这种情况下,输出 jar 文件无法从主类 ( miner.Tracker ) 加载主要方法。

As I mentioned, a run with -jar option failed.正如我所提到的,使用-jar选项运行失败。

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

I also tried to directly run the class with -cp option but it failed.我还尝试使用-cp选项直接运行该类,但失败了。

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

Lastly, I uncompressed the jar file and call the class from inside.最后,我解压缩了 jar 文件并从内部调用该类。 This time, it has succeeded to find and run the class with the main method.这一次,它已经成功地找到并运行了带有 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
...

Here's the contents of META-INF/MANIFEST.MF file.这是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

And I am running it from Oracle Java 1.8.我从 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)

Thanks for your help.谢谢你的帮助。


Update:更新:

$ 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

After some experimentation, I agree with user 11thdimension that something might be wrong with your manifest file.经过一些实验,我同意用户第 11维的观点,即您的清单文件可能有问题。 I do not think that it is about the non-numeric versions, though.不过,我认为这与非数字版本无关。 I tried, it works.我试过了,有效。

What I did notice is that if you add a line which contains more than a normal space (character 32 dec, 20 hex), you are going to see the error you described, simply because the manifest cannot be parsed.我注意到的是,如果您添加的行包含的空间超过正常空间(字符 32 dec, 20 hex),您将看到您描述的错误,因为清单无法解析。 Obviously the manifest parser expects something like MyKey: MyValue on each non-empty line.显然,清单解析器在每个非空行上都需要类似MyKey: MyValue东西。 Even empty lines anywhere else than at the end can cause the same problem, if they are in the middle of a so-called section.即使在末尾以外的任何地方的空行也可能导致相同的问题,如果它们位于所谓的部分的中间。 So if you have manifests like one of the following, you are going to see a ClassNotFoundException , no matter if you use -cp or -jar :因此,如果您有类似以下之一的清单,无论您使用-cp还是-jar ,您都会看到ClassNotFoundException

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

Main-Class: miner.Tracker

Even if at after the last line you have a line containing just a tab character like this, the error occurs:即使在最后一行之后你有一行只包含这样的制表符,也会发生错误:

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

The same is true if you have lines using other invisible characters, such as non-standard Unicode spaces .如果您有使用其他不可见字符(例如非标准Unicode 空格)的行,情况也是如此。

Like I said in my previous comment: Check for such characters anywhere in your manifest.就像我在之前的评论中所说的那样:检查清单中任何位置的此类字符。 If that does not yield any results, please also check your Java source code files, especially package and class names.如果这没有产生任何结果,还请检查您的 Java 源代码文件,尤其是包和类名称。


Update: Here is a little Java example showcasing what I explained before:更新:这是一个小 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

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

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