简体   繁体   中英

Cannot run JAR file due to cannot load main class error

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.

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

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

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

Here's the contents of META-INF/MANIFEST.MF file.

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.

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

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

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.


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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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