由于无法加载主类错误而无法运行JAR文件 [英] Cannot run JAR file due to cannot load main class error

查看:111
本文介绍了由于无法加载主类错误而无法运行JAR文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I built my project and generated a JAR file using Gradle build framework. However, the output jar file fails to load the main methods from the main class (miner.Tracker) in this case.

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

As I mentioned, a run with -jar option failed.

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

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

I also tried to directly run the class with -cp option but it failed.

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

最后,我解压缩了jar文件并从内部调用该类.这次,它已经成功地使用main方法找到并运行了该类.

Lastly, I uncompressed the jar file and call the class from inside. This time, it has succeeded to find and run the class with the main method.

$ 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运行它.

And I am running it from 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

推荐答案

经过一些试验,我同意用户 11thmension 您的清单文件可能有问题.不过,我认为这与非数字版本无关.我试过了,可以用.

After some experimentation, I agree with user 11thdimension that something might be wrong with your manifest file. I do not think that it is about the non-numeric versions, though. I tried, it works.

我确实注意到的是,如果添加的行包含的空间超出正常范围(字符32 dec,十六进制20),您将看到您所描述的错误,仅仅是因为无法解析清单.显然,清单分析器在每个非空行上都需要类似 MyKey:MyValue 的内容.如果空行位于末尾的中间,那么即使结尾处的空行也可能导致相同的问题.因此,如果您具有类似以下内容之一的清单,则无论使用 -cp 还是 -jar ,您都将看到 ClassNotFoundException :

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. Obviously the manifest parser expects something like MyKey: MyValue on each non-empty line. 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:

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
    

如果您使用其他不可见字符(例如非标准 Unicode空格.

The same is true if you have lines using other invisible characters, such as non-standard Unicode spaces.

就像我在以前的评论中所说的那样:检查清单中任何位置的此类字符.如果仍然无法产生任何结果,请检查您的Java源代码文件,尤其是程序包和类名.

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:

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

这篇关于由于无法加载主类错误而无法运行JAR文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆