简介
当将 Java 应用程序打包并作为 JAR(Java Archive)文件运行时,开发者经常会遇到 'no main manifest attribute' 错误。当尝试执行 JAR 文件时,如果 Java 虚拟机(JVM)无法确定哪个类包含 main 方法来启动应用程序,就会发生此错误。
本实验将指导你理解、诊断和解决这个常见错误。通过本教程,你将知道如何使用清单文件正确配置 JAR 文件,从而正确指定主类。
当将 Java 应用程序打包并作为 JAR(Java Archive)文件运行时,开发者经常会遇到 'no main manifest attribute' 错误。当尝试执行 JAR 文件时,如果 Java 虚拟机(JVM)无法确定哪个类包含 main 方法来启动应用程序,就会发生此错误。
本实验将指导你理解、诊断和解决这个常见错误。通过本教程,你将知道如何使用清单文件正确配置 JAR 文件,从而正确指定主类。
让我们从创建一个简单的 Java 应用程序开始,我们将把它打包成一个 JAR 文件。这将帮助我们演示并稍后修复 'no main manifest attribute' 错误。
首先,为我们的 Java 源代码文件创建一个目录,并导航到该目录:
cd ~/project/src/com/example
现在,打开编辑器并在该目录中创建一个名为 HelloWorld.java
的新文件:
/home/labex/project/src/com/example
HelloWorld.java
将以下代码添加到 HelloWorld.java
文件中:
package com.example;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
这是一个基本的 Java 程序,它有一个 main
方法,当执行时,它将向控制台打印 "Hello, World!"。
现在,让我们编译我们的 Java 类。返回到终端并导航到项目根目录:
cd ~/project
使用 javac
命令编译 Java 文件:
javac -d . src/com/example/HelloWorld.java
此命令编译 Java 源代码文件,并根据包名将编译后的类文件放置在适当的目录结构中。
你现在应该在 ~/project/com/example/HelloWorld.class
处有一个编译后的类文件。你可以使用以下命令进行验证:
ls -l com/example/
输出应该显示 HelloWorld.class
文件:
total 4
-rw-r--r-- 1 labex labex 426 [date] HelloWorld.class
现在,让我们创建一个 JAR 文件,而不指定清单文件中的主类。这将允许我们重现 'no main manifest attribute' 错误:
jar cf HelloWorld.jar com/
此命令创建一个名为 HelloWorld.jar
的 JAR 文件,其中包含编译后的类文件。
现在我们已经创建了我们的 JAR 文件,让我们尝试运行它:
java -jar HelloWorld.jar
你将看到错误消息:
no main manifest attribute, in HelloWorld.jar
这就是我们正在学习修复的错误。JVM 找不到要执行的 main 类,因为我们没有在 JAR 的清单文件中指定它。
在这一步中,我们将探讨 'no main manifest attribute' 错误的原因,并了解 JAR 文件清单的工作原理。
JAR 文件在 META-INF
目录中包含一个名为 MANIFEST.MF
的特殊文件。此清单文件包含有关 JAR 及其内容的元数据。清单可以包含的一个重要信息是 Main-Class
属性,它告诉 JVM 哪个类包含在运行 JAR 时要执行的 main 方法。
让我们检查一下我们 JAR 文件中的当前清单:
mkdir -p temp_dir
cd temp_dir
jar xf ../HelloWorld.jar META-INF/MANIFEST.MF
cat META-INF/MANIFEST.MF
你将看到一个最小的清单,它看起来像这样:
Manifest-Version: 1.0
Created-By: 1.8.0_XXX (Oracle Corporation)
请注意,此清单中没有 Main-Class
属性,这就是我们在尝试运行 JAR 时收到 'no main manifest attribute' 错误的原因。
为了更好地理解我们的 JAR 文件,让我们看看它的内容:
cd ~/project
jar tf HelloWorld.jar
此命令列出 JAR 中的所有文件。输出应该类似于:
META-INF/
META-INF/MANIFEST.MF
com/
com/example/
com/example/HelloWorld.class
正如我们所看到的,我们的 JAR 包含编译后的类文件,正如预期的那样,但清单没有识别主类所需的信息。
'no main manifest attribute' 错误通常发生在以下情况:
java -jar
运行 JAR 文件,但 JAR 并非旨在可执行Main-Class
属性在我们的例子中,我们故意创建了一个 JAR,没有指定主类来演示该错误。
让我们清理我们的临时目录:
cd ~/project
rm -rf temp_dir
现在我们了解了错误的原因,在下一步中,我们将通过创建一个正确的清单文件来修复它。
现在我们了解了问题,让我们通过创建一个指定主类的正确清单文件来修复它。
首先,导航回项目目录:
cd ~/project
现在,创建一个名为 manifest.txt
的文本文件:
/home/labex/project
manifest.txt
将以下内容添加到 manifest.txt
文件中:
Main-Class: com.example.HelloWorld
确保在文件末尾添加一个换行符(清单格式要求文件以换行符结尾)。在 WebIDE 中,只需在键入以上行后按 Enter 键即可。
这个简单的清单文件指定了 com.example.HelloWorld
类包含在运行 JAR 时应该执行的 main 方法。
现在,创建一个新的 JAR 文件,这次包括我们的自定义清单:
jar cfm HelloWorldWithManifest.jar manifest.txt com/
此命令创建一个名为 HelloWorldWithManifest.jar
的新 JAR 文件,其中包含编译后的类文件,并使用我们的自定义清单文件。
此命令中使用的选项是:
c
: 创建一个新归档文件f
: 指定归档文件名m
: 从指定的清单文件包含清单信息让我们检查一下我们的清单是否已正确包含在 JAR 中:
mkdir -p temp_check
cd temp_check
jar xf ../HelloWorldWithManifest.jar META-INF/MANIFEST.MF
cat META-INF/MANIFEST.MF
你应该看到清单现在包括我们的 Main-Class
属性:
Manifest-Version: 1.0
Created-By: [Java version info]
Main-Class: com.example.HelloWorld
现在,让我们清理临时目录:
cd ~/project
rm -rf temp_check
现在我们已经创建了一个具有指定主类的正确清单文件的 JAR 文件,让我们运行它并验证它是否正常工作。
确保你在项目目录中:
cd ~/project
现在,使用 java -jar
命令运行 JAR 文件:
java -jar HelloWorldWithManifest.jar
这次,你不会看到 'no main manifest attribute' 错误,你应该看到我们程序的输出:
Hello, World!
恭喜你。你已经通过创建一个指定主类的正确清单文件,成功修复了 'no main manifest attribute' 错误。
让我们花点时间来理解我们做了什么来修复这个错误:
Main-Class
属性,告诉 JVM 哪个类包含要执行的 main 方法java -jar
命令运行了 JAR,并且 JVM 能够找到并执行 main 方法在使用 JAR 文件时,还有其他几种指定主类的方法:
除了创建单独的清单文件之外,你还可以使用 e
选项在创建 JAR 时直接指定主类:
jar cfe HelloWorldDirect.jar com.example.HelloWorld com/
这将创建一个名为 HelloWorldDirect.jar
的新 JAR 文件,其主类指定为 com.example.HelloWorld
。
让我们运行这个 JAR 来验证它是否有效:
java -jar HelloWorldDirect.jar
你应该看到输出:
Hello, World!
如果你有一个没有正确清单的 JAR 文件,你仍然可以通过在 java
命令中直接指定主类来运行它:
java -cp HelloWorld.jar com.example.HelloWorld
此命令告诉 JVM 在类路径 (-cp
) 中使用 HelloWorld.jar
并执行 com.example.HelloWorld
类。
你应该看到输出:
Hello, World!
这种方法通过显式地告诉 JVM 要执行哪个类来绕过对清单的需求。
在这个实验中,你学习了 Java 中的 'no main manifest attribute' 错误以及如何解决它。让我们回顾一下我们所涵盖的内容:
理解错误:当 JVM 无法在 JAR 文件中找到要执行的 main 类时,就会发生 'no main manifest attribute' 错误,因为它未在清单中指定。
创建正确的清单:你学习了如何使用 Main-Class
属性创建一个指定主类的清单文件。
使用清单构建 JAR 文件:你学习了如何创建包含清单信息的 JAR 文件:
jar cfm ...
)jar cfe ...
)运行 JAR 文件:你学习了以不同方式运行打包为 JAR 文件的 Java 应用程序:
java -jar
和正确配置的清单java -cp
显式指定类路径和主类这些技能对于需要将应用程序打包并分发为 JAR 文件的 Java 开发人员至关重要。通过理解清单的作用以及如何正确配置它,你可以避免 'no main manifest attribute' 错误,并确保你的 Java 应用程序顺利运行。
请记住,正确的打包与编写好的代码一样重要。花时间正确设置你的构建和打包将为你和你的用户节省以后的麻烦。