Reputation: 427
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
Upvotes: 5
Views: 2020
Reputation: 67297
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
Upvotes: 6