如果 MANIFEST.MF 不存在,什么定义了主 class

What defines the main class if MANIFEST.MF is not present

在 Eclipse 中导出到 JAR 时有两个选项:导出为可运行的 JAR 和导出为 JAR。

我了解到可运行的 jar 包含一个 MANIFEST.MF 文件,它定义了执行 jar 时要执行的 Main class。

我还了解到,不可运行的 jar 只是 classes 的库,可以将其添加到 class 路径,以便重复使用代码。它包含一个清单文件,但其中没有定义的主要内容 class。

如果未定义 main class,那么不可运行的 JAR 文件如何能够执行?有一个定义主要 class 的 MANIFEST.MF 文件有什么 pros/cons?一个比另一个更稳定?

What defines the main class if MANIFEST.MF is not present

如果 JAR 文件没有“META-INF/MANIFEST.MF”组件,则它不是 JAR 文件。它只是一个 ZIP 文件,您不能对 ZIP 文件使用 java -jar ...。 (您可以在 class 路径中包含一个 ZIP 文件,但通常不会这样做。)

如果 JAR 文件具有 MANIFEST.MF 而没有 Main-Class 属性,则不是 可执行的 JAR 文件,并且 java -jar ... 将失败。

但是(如前所述)许多 JAR 文件是库而不是应用程序。对他们来说,入口点 class 毫无意义。


How is a non-runnable JAR file able to execute if the main class is not defined?

(首选 Java 术语是“可执行”而不是“运行可执行”。)

在这种情况下,java -jar ... 将失败。相反,您可以 运行 像这样的应用程序:

  java -cp <classpath> <other-options> com.example.MyApp.Main <args>

其中 com.example.MyApp.Main 是主要/入口点 class,<classpath> 包括 JAR(或 ZIP)文件和任何其他 运行 时间依赖项。

请注意,一个应用程序 JAR 文件 可以 包含多个入口点 class,并且用户可以决定使用哪一个。


What are the pros/cons of having a MANIFEST.MF file that defines the main class?

首先,如果您使用 jar 命令创建 JAR 文件,那么它 将有一个 MANIFEST.MF。如果没有 JAR,该命令将不会创建 JAR。

此外,您还可以在 MANIFEST.MF 中包含其他有用的内容。这些包括数字哈希(用于签名的 JAR)和一个 Class-Path 属性,用于在使用 -jar 启动 JAR 时使用。有关详细信息,请参阅 JAR file specification.

在 JAR 文件中具有 Main-Class 属性的优点是:

  1. 如果要使用-jar是必须的。
  2. 这意味着用户不需要知道(或键入)入口点的全名class。

具有 Main-Class 属性没有明显的缺点。如果用户不使用 java -jar ... 启动方法,那么任何此类属性都将被忽略。但我想您可能会说,将无意义的 Main-Class 属性放在 library JAR 上可能会导致天真的用户产生误导性错误。真是吹毛求疵...


Is one more stable than the other?

不直接。

您可能会争辩说 使用 -jar 更稳定,因为可执行 JAR 会忽略 CLASSPATH 环境变量和 -cp 参数命令行。但不利的一面是,您不能强制用户使用 -jar(或双击)来启动命令。您可以通过提供 shell 脚本或 BAT 文件来获得类似的稳定性,以使用适当的入口点 class 名称和适当的 class 路径启动应用程序。


I executed a non-runnable jar in Eclipse without the classpath or project files and then I ran it and it worked. It was able to identify the main class and run it from there. my question is: how was it able to identify it?

好的...这是一个不同的问题。

这里实际发生的是 Eclipse 项目有一堆配置信息,其中包括 build 依赖项。这些为 Eclipse 启动器提供了默认的 class 路径。然后,当您在没有现有 运行 配置的情况下使用 Eclipse 的 run 命令时,Eclipse 将搜索当前项目中的所有 classes 以查找 any class 使用 public static void main(String[]) 方法。如果它只找到一个这样的 class,它 假定 它是入口点 class,并为项目创建一个 运行 配置 / class。启动该配置后,Eclipse 会执行 java -cp <classpath> <class-name> <args>.

的等效操作

备注:

  1. 这是 Eclipse 特定行为。标准 Java 工具链不会做这样的事情。

  2. Eclipse 未在此处使用 java -jar,因此不会参考清单来查找入口点 class.

  3. 这已被破解。例如,我听说如果您删除主 class 并创建一个新的,启动配置不会更新,并且当您尝试“运行”它时会出现 JVM 启动错误.

“运行nable jar”是一个 jar 文件,其中清单文件包含允许 java Java 运行ner 命令“运行" 以更简单的方式生成 jar 文件。

例如如果 Foo.jar 文件在包 com.example 中的 class Bar 中有一个 static void main(String[]) 方法,那么您可以 运行 该程序使用:

java -cp Foo.jar com.example.Bar

如果 jar 文件清单文件包含以下行:

Main-Class: com.example.Bar

然后你可以运行 jar 文件我更简单的方法:

java -jar Foo.jar

当然,如果没有class和main()方法,那么jar文件中的代码就不是“运行nable”,因此只是一个库文件。

真的就这些了。

参见例如The Java™ Tutorials - Setting an Application's Entry Point 获取更多信息。