1. 简介

Java Archive(JAR)文件通过其 清单文件(Manifest) 来描述自身。清单文件不仅用于定义 JAR 的基本属性,还可以指定可执行类、版本信息、依赖路径等。本文将带你了解 JAR 清单文件的结构、常见用途以及如何自定义它。

2. 什么是清单文件

清单文件名为 MANIFEST.MF,位于 JAR 包的 META-INF/ 目录下。它是 一组键值对(headers) 的集合,这些 headers 分组组织,用于描述 JAR 的各种元信息。

比如:

✅ 可执行类入口(Main-Class)
✅ 类路径(Class-Path)
✅ 版本信息(Implementation-Version)
✅ 包签名信息(用于安全校验)
✅ OSGi 模块信息(Bundle-SymbolicName 等)

3. 如何添加清单文件

3.1. 默认清单文件

当我们使用 jar 命令打包时,JDK 会自动生成一个默认的 MANIFEST.MF 文件。

例如:

jar cf MyJar.jar classes/

生成的默认内容如下:

Manifest-Version: 1.0
Created-By: 11.0.3 (AdoptOpenJDK)

3.2. 自定义清单文件

我们也可以自定义清单内容。例如创建一个名为 manifest.txt 的文件:

Built-By: baeldung

使用 -m 参数将其合并到默认清单中:

jar cfm MyJar.jar manifest.txt classes/

生成的清单内容如下:

Manifest-Version: 1.0
Built-By: baeldung
Created-By: 11.0.3 (AdoptOpenJDK)

⚠️ 注意:

  • 键和值之间必须有一个空格
  • 文件结尾必须有一个空行,否则最后一行会被忽略

3.3. 使用 Maven 自定义

Maven 构建的 JAR,默认清单会包含额外信息,如:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven 3.3.9
Built-By: baeldung
Build-Jdk: 11.0.3

我们可以通过配置 maven-jar-plugin 插件来自定义:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.3.0</version>
    <configuration>
        <archive>
            <manifest>
                <packageName>com.baeldung.java</packageName>
            </manifest>
            <manifestEntries>
                <Created-By>baeldung</Created-By>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

输出如下:

Manifest-Version: 1.0
Build-Jdk-Spec: 11
Package: com.baeldung.java
Created-By: baeldung

📌 更多配置项可参考:Maven JAR Plugin 官方文档

4. 清单文件中的常用 Headers

4.1. 主要 Headers

Header 说明
Manifest-Version 清单规范版本号
Created-By 创建工具和版本
Multi-Release 是否为多版本 JAR(Multi-Release JAR)
Built-By 构建者名称(自定义)

4.2. 可执行入口和类路径

Header 说明
Main-Class 应用主类(含包名,无 .class 后缀)
Class-Path 依赖的外部资源路径(空格分隔)

示例:

Main-Class: com.baeldung.Application
Class-Path: core.jar lib/ properties/

⚠️ 注意:

  • Class-Path 指的是 JAR 外部资源路径
  • 这些资源必须在运行时所在目录下存在

4.3. 包版本与封包信息

Header 说明
Name 包路径
Implementation-Title 实现标题
Implementation-Version 实现版本
Implementation-Vendor 实现厂商
Specification-Title 规范标题
Specification-Version 规范版本
Specification-Vendor 规范厂商
Sealed 是否封包(true/false)

MySQL Connector/J 示例:

Specification-Title: JDBC
Specification-Version: 4.2
Specification-Vendor: Oracle Corporation
Implementation-Title: MySQL Connector/J
Implementation-Version: 8.0.16
Implementation-Vendor: Oracle

4.4. 签名信息

如果 JAR 被数字签名,清单中会包含如下内容:

  • 每个签名类的名称
  • 签名的编码信息

这部分内容由 jarsigner 工具自动生成,不在本文详细讨论范围。详见:JAR Signing 官方文档

4.5. OSGi 模块信息

如果你使用 OSGi 框架,常见 headers 如下:

Header 说明
Bundle-Name 模块标题
Bundle-SymbolicName 模块唯一标识
Bundle-Version 模块版本
Import-Package 依赖的包
Export-Package 导出的包

更多内容请参考:OSGi Bundle Headers

5. 清单文件中的 Section 分组

清单文件可以包含多个 Section(段),分为两类:

  • Main Section:作用于整个 JAR
  • Per-Entry Section:仅作用于特定类或包

例如:

Implementation-Title: baeldung-examples 
Implementation-Version: 1.0.1
Implementation-Vendor: Baeldung
Sealed: true

Name: com/baeldung/utils/
Sealed: false

📌 说明:

  • 主段中设置了 Sealed: true,表示所有包默认封包
  • com.baeldung.utils 包通过 per-entry section 设置为 Sealed: false,覆盖了主段设置

6. 总结

清单文件(MANIFEST.MF)是 JAR 包的重要组成部分,它提供了:

✅ 可执行信息(Main-Class)
✅ 类路径信息(Class-Path)
✅ 版本与厂商信息(Implementation/Specification)
✅ 签名与安全信息
✅ OSGi 模块信息
✅ 包级别的元信息控制(通过 Section 分组)

合理使用清单文件,可以提升 JAR 的可维护性、安全性以及模块化能力。同时,它也为我们提供了一种灵活的元数据描述方式。


原始标题:Understanding the JAR Manifest File