1. 概述

每个可执行的 Java 类都必须包含一个 main() 方法——这是整个应用的入口点,这点大家都知道 ✅。

但当我们想通过 java -jar example.jar 直接运行一个 JAR 包时,却经常遇到这个经典报错:

no main manifest attribute, in example.jar

这个错误的意思很明确:JAR 包的 MANIFEST.MF 文件中缺少 Main-Class 声明,导致 JVM 找不到入口类 ❌。

本文将带你从零构建一个可执行 JAR,深入理解 Main-Class 的作用,并总结常见“踩坑”点。最后还会覆盖 Maven、Gradle、Ant 和主流 IDE 的配置方式,确保你以后打包不再翻车。


2. 没有 Main Manifest 属性时的执行尝试

我们先写一个最简单的入口类:

public class AppExample {
    public static void main(String[] args){
        System.out.println("AppExample executed!");
    }
}

编译并打包成 JAR(不带自定义 manifest):

javac -d . AppExample.java
jar cvf example.jar com/baeldung/manifest/AppExample.class

此时 JAR 内会包含一个默认的 MANIFEST.MF,但里面没有 Main-Class

执行:

java -jar example.jar

结果报错:

no main manifest attribute, in example.jar

2.1 手动指定主类绕过问题

虽然不能用 -jar,但我们可以通过 -cp 手动指定类路径和主类来运行:

java -cp example.jar com/baeldung/manifest/AppExample

或等价写法:

java -classpath example.jar com/baeldung/manifest/AppExample

✅ 输出正常:

AppExample executed!

⚠️ 注意:这种方式需要用户知道主类全名,不适合分发。真正的“可执行 JAR”应该做到开箱即用,-jar 直接运行。


3. 正确添加 Main Manifest 属性

要让 JAR 支持 java -jar,必须在 MANIFEST.MF 中声明 Main-Class

创建文件 MANIFEST.MF,内容如下:

Main-Class: com.baeldung.manifest.AppExample

⚠️ 注意:

  • 类名必须是全限定名(包含 package)
  • 行尾必须有换行符(下文会强调)

使用 -m 参数将自定义 manifest 打包进 JAR:

jar cvmf MANIFEST.MF example.jar com/baeldung/manifest/AppExample.class

再次执行:

java -jar example.jar

✅ 成功输出:

AppExample executed!

4. 构建可执行 JAR 的常见踩坑点

即使加了 Main-Class,仍可能报错。以下是几个经典翻车场景 ⚠️。

4.1 Main-Class 类名拼写错误

最常见问题:类名写错或漏了包路径。

❌ 错误示例:

Main-Class: AppExample

✅ 正确应为:

Main-Class: com.baeldung.manifest.AppExample

Java 会严格按照这个全限定名去加载类,差一个字母都找不到 ❌。

4.2 manifest 文件末尾缺少空行

这是很多人忽略的细节:JAR 的 manifest 文件每一项必须以换行结束,且文件末尾必须有一个空行

❌ 错误写法(无结尾换行):

Main-Class: com.baeldung.manifest.AppExample

✅ 正确写法(末尾有换行):

Main-Class: com.baeldung.manifest.AppExample
[此处有一个空行]

如果没有这个空行,JVM 可能无法正确解析 manifest,导致 Main-Class 被忽略。

4.3 manifest 文件位置或打包方式错误

使用 jar 命令时,如果没用 -m 指定自定义 manifest,就会使用默认的,而默认的没有 Main-Class

另外,手动解压 JAR 后检查,MANIFEST.MF 必须位于:

META-INF/MANIFEST.MF

如果路径不对,或者被打包到了其他目录,JVM 也找不到。


5. 使用构建工具自动添加 Main-Class

手动维护 MANIFEST.MF 太原始了。现代项目推荐用构建工具自动生成,更可靠 ✅。

5.1 Maven 配置

pom.xml 中配置 maven-jar-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.2.2</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>com.baeldung.manifest.AppExample</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

执行:

mvn package

生成的 JAR 位于 target/ 目录,manifest 已自动包含 Main-Class

5.2 Gradle 配置

build.gradle 中添加:

jar {
    manifest {
        attributes(
            'Main-Class': 'com.baeldung.manifest.AppExample'
        )
    }
}

执行:

gradle build

可执行 JAR 生成在 build/libs/

💡 提示:如果你用 application 插件,可以直接用 mainClassNamemainClass 属性,更简单。

5.3 Ant 配置

build.xml 中:

<target name="jar" depends="compile">
    <jar destfile="dist/example.jar" basedir="build/classes">
        <manifest>
            <attribute name="Main-Class" value="com.baeldung.manifest.AppExample"/>
        </manifest>
    </jar>
</target>

Ant 会自动在 META-INF/ 下生成正确的 MANIFEST.MF

5.4 IDE 配置(IntelliJ & Eclipse)

IntelliJ IDEA

  1. File > Project Structure > Artifacts
  2. + > JAR > From modules with dependencies
  3. 选择模块和主类
  4. 勾选 “Extract to the target JAR”
  5. Build > Build Artifacts

✅ 生成的 JAR 自带正确 manifest。

Eclipse

  1. 右键项目 → Export
  2. 选择 Runnable JAR file
  3. 选择运行配置(即主类)
  4. 设置输出路径和库依赖处理方式
  5. 点击 Finish

Eclipse 会自动创建 MANIFEST.MF 并设置 Main-Class,简单粗暴但有效。


6. 总结

  • Main-Class 是可执行 JAR 的核心,缺了它 java -jar 就会报 no main manifest attribute
  • 手动打包时务必:
    • ✅ 使用全限定类名
    • ✅ manifest 文件末尾加空行
    • ✅ 用 jar cvmf 正确打包
  • 推荐使用构建工具(Maven/Gradle)或 IDE 自动生成 manifest,避免手写出错 ✅
  • 遇到问题先检查:
    • JAR 包内 META-INF/MANIFEST.MF 是否存在
    • Main-Class 是否拼写正确
    • 文件末尾是否有换行

掌握了这些,以后打包 JAR 再也不会被这个低级错误卡住。


原始标题:Importance of Main Manifest Attribute in a Self-Executing JAR | Baeldung