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 的可维护性、安全性以及模块化能力。同时,它也为我们提供了一种灵活的元数据描述方式。