Java 打包详解:使用 jar 命令创建与管理 JAR 文件
JAR(Java Archive)文件是 Java 平台中用于打包类、资源和元数据的归档格式,可用于分发库、应用程序或组件。jar
命令是 JDK 自带的打包工具,支持创建、查看、更新和提取 JAR 文件。本文将详细讲解 jar
命令的用法、参数含义及实战示例,帮助你熟练掌握 Java 打包技巧。
jar 命令基本语法
jar
命令的通用格式如下:
1 | jar {操作选项}[参数] [JAR文件名] [清单文件] [入口类] [-C 目录] 文件... |
核心操作选项(必选其一)
选项 | 功能描述 |
---|---|
-c |
创建新的 JAR 文件(若文件已存在,会覆盖)。 |
-t |
列出 JAR 文件中的内容(目录和文件列表)。 |
-x |
从 JAR 文件中提取指定文件(不指定则提取所有文件)。 |
-u |
更新现有 JAR 文件(添加新文件或替换已有文件)。 |
-i |
为 JAR 文件生成索引信息(加速类加载)。 |
辅助参数(可选)
选项 | 功能描述 |
---|---|
-v |
生成详细输出(显示打包 / 提取的文件列表及进度)。 |
-f |
指定 JAR 文件名(必须紧跟文件名,如 -f app.jar )。 |
-m |
合并指定的清单文件(MANIFEST.MF )到 JAR 中(需指定清单文件路径)。 |
-e |
指定可执行 JAR 的入口类(主类,包含 main 方法)。 |
-0 |
仅存储文件,不压缩(适合已压缩的资源,如图片、ZIP)。 |
-M |
不自动生成清单文件(默认会生成基础清单)。 |
-C |
切换到指定目录,再包含后续文件(用于打包其他目录的文件,保持目录结构)。 |
-P |
保留文件的绝对路径或父目录信息(不推荐,可能导致路径混乱)。 |
jar 命令实战示例
创建 JAR 文件
(1)基本打包(含类文件)
将当前目录下的 Foo.class
和 Bar.class
打包为 classes.jar
:
1 | jar cvf classes.jar Foo.class Bar.class |
c
:创建新 JAR;v
:显示详细信息;f
:指定文件名classes.jar
。输出示例:
1
2
3已添加清单
正在添加: Foo.class(输入 = 890) (输出 = 543)(压缩了 38%)
正在添加: Bar.class(输入 = 1024) (输出 = 621)(压缩了 39%)
(2)打包目录(含子目录)
将 src
目录下的所有文件(含子目录)打包为 app.jar
:
1 | jar cvf app.jar src/ |
- 注意:目录会被递归处理,保留原目录结构(如
src/com/xxx/Class.class
)。
(3)指定清单文件
使用自定义清单文件 mymanifest.mf
打包(覆盖默认清单):
1 | jar cvfm app.jar mymanifest.mf -C bin/ . |
-m
:指定清单文件mymanifest.mf
;-C bin/ .
:切换到bin
目录,打包所有文件(.
表示当前目录,即bin
下的内容)。
(4)创建可执行 JAR(带主类)
打包并指定入口类 com.example.Main
(含 main
方法),可直接通过 java -jar
运行:
1 | jar cvfe app.jar com.example.Main -C target/classes/ . |
-e com.example.Main
:指定主类;- 运行方式:
java -jar app.jar
。
查看 JAR 文件内容
列出 app.jar
中的所有文件和目录:
1 | jar tf app.jar # 简洁输出 |
输出示例(简洁版):
1
2
3
4
5META-INF/
META-INF/MANIFEST.MF
com/
com/example/
com/example/Main.class
提取 JAR 文件内容
(1)提取所有文件
将 app.jar
中的所有内容提取到当前目录:
1 | jar xf app.jar |
- 提取后会还原 JAR 中的目录结构(如
META-INF/
、com/
等)。
(2)提取指定文件
仅提取 app.jar
中的 com/example/Main.class
:
1 | jar xf app.jar com/example/Main.class |
更新 JAR 文件
向现有 app.jar
中添加新文件 config.properties
:
1 | jar uf app.jar config.properties |
- 若文件已存在,会覆盖旧版本;
- 加
-v
可查看详细更新信息:jar uvf app.jar config.properties
。
生成索引文件
为大型 JAR 生成索引(加速类加载,多 JAR 依赖时有用):
1 | jar i app.jar |
- 生成
META-INF/INDEX.LIST
,记录 JAR 中的类信息。
清单文件(MANIFEST.MF)详解
清单文件是 JAR 中的元数据文件,位于 META-INF/MANIFEST.MF
,用于描述 JAR 的属性(如主类、版本、依赖等)。
默认清单内容
创建 JAR 时,若不指定 -m
,会自动生成基础清单:
1 | Manifest-Version: 1.0 |
关键属性(自定义清单)
属性 | 作用描述 |
---|---|
Main-Class |
可执行 JAR 的入口类(如 com.example.Main ),配合 java -jar 运行。 |
Class-Path |
指定 JAR 依赖的其他 JAR 路径(空格分隔,相对路径)。 |
Implementation-Title |
应用名称。 |
Implementation-Version |
应用版本。 |
示例:可执行 JAR 的清单
1 | Manifest-Version: 1.0 |
- 打包时通过
-m
引入该清单:jar cvfm app.jar manifest.mf -C classes/ .
。
清单文件格式注意事项
- 每行格式:
属性名: 值
(冒号后必须有空格)。 - 换行规则:长行需在第二行开头加空格(续行)。
- 编码:默认 UTF-8,不可包含非 ASCII 字符(除非编码正确)。
可执行 JAR 的运行与原理
运行可执行 JAR
1 | java -jar app.jar |
要求清单文件中指定Main-Class,否则需手动指定主类:
1
java -cp app.jar com.example.Main # -cp 指定类路径
原理
- 可执行 JAR 本质是包含
Main-Class
属性的普通 JAR。 java -jar
会优先读取清单中的Main-Class
,并调用其main
方法。
常见问题与解决方案
1. “没有主清单属性” 错误
- 原因:JAR 未指定
Main-Class
,或清单格式错误。 - 解决:重新打包并通过
-e
指定主类,或在清单中添加Main-Class: 全类名
。
2. 依赖 JAR 无法找到
- 原因:依赖的 JAR 不在
Class-Path
指定的路径下。 - 解决:
- 在清单中通过
Class-Path
正确配置依赖路径(相对或绝对路径)。 - 或使用工具(如 Maven/Gradle)将依赖打包到 JAR 中(-fat jar)。
- 在清单中通过
3. 中文文件名乱码
原因:
jar
命令依赖系统默认编码,非 UTF-8 环境可能乱码。解决:指定编码(仅部分 JDK 版本支持):
1
jar cvf app.jar -Dfile.encoding=UTF-8 文件名
v1.3.10