kje*_*jee 5 java program-entry-point jar build manifest
我使用 Gradle 构建框架构建了项目并生成了 JAR 文件。但是,输出 jar 文件无法从主类(miner.Tracker。
正如我提到的,使用选项运行-jar失败。
$ java -jar Backtracker.jar
Error: Could not find or load main class miner.Tracker
Run Code Online (Sandbox Code Playgroud)
我也尝试直接使用选项运行该类-cp,但失败了。
$ java -cp Backtracker.jar miner.Tracker
Error: Could not find or load main class miner.Tracker
Run Code Online (Sandbox Code Playgroud)
最后,我解压缩了 jar 文件并从内部调用该类。这次,它成功找到并运行了具有 main 方法的类。
$ java -cp Backtracker.jar miner.Tracker
Error: Could not find or load main class miner.Tracker
Run Code Online (Sandbox Code Playgroud)
这是文件的内容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
Run Code Online (Sandbox Code Playgroud)
我从 Oracle Java 1.8 运行它。
$ 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
...
Run Code Online (Sandbox Code Playgroud)
感谢您的帮助。
更新:
Manifest-Version: 1.0
Implementation-Title: BackTracker
Implementation-Version: 1.9.xx
Specification-Title: release
Specification-Version: 1.9.xx
Main-Class: miner.Tracker
Run Code Online (Sandbox Code Playgroud)
经过一些实验,我同意用户11thdimension 的观点,即您的清单文件可能有问题。不过,我认为这与非数字版本无关。我试过了,有效。
我注意到的是,如果您添加一行包含超过正常空格(字符 32 dec,20 hex),您将看到您所描述的错误,仅仅是因为无法解析清单。显然,清单解析器期望MyKey: MyValue每个非空行上都有类似的内容。如果空行位于所谓的部分的中间,那么即使不是末尾处的空行也可能会导致相同的问题。因此,如果您有类似以下之一的清单,ClassNotFoundException无论您是否使用-cp或,您都将看到-jar:
Manifest-Version: 1.0
Main-Class: miner.Tracker
x
Run Code Online (Sandbox Code Playgroud)
Manifest-Version: 1.0
Main-Class: miner.Tracker
Run Code Online (Sandbox Code Playgroud)
即使在最后一行之后有一行只包含一个制表符,如下所示,也会发生错误:
Manifest-Version: 1.0
Main-Class: miner.Tracker
Run Code Online (Sandbox Code Playgroud)
如果您的行使用其他不可见字符(例如非标准Unicode 空格) ,情况也是如此。
就像我在之前的评论中所说:检查清单中的任何位置是否有此类字符。如果这没有产生任何结果,还请检查您的 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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
[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
Run Code Online (Sandbox Code Playgroud)