jar命令(一)-jar打包class文件

Java Jar包实战
本文详细介绍如何使用Java的jar命令创建可执行的jar包,包括单个class文件的打包及带有清单文件的打包过程。文中还提供了多种方法实现主类属性的配置,确保jar包能够被正确执行。

jar包本质上是将所有class文件、资源文件压缩打成一个包(也可以选择不压缩),可选择在jar包中生成META-INF/MANIFEST.MF文件,MANIFEST.MF是清单文件,里面可以记录主类、classpath等信息,供虚拟机使用。
接下来的一段时间里,我们将以以下路径学习jar命令和清单文件的相关知识

  1. jar打包class文件
  2. 带包class文件jar打包
  3. 清单文件的使用

在这篇文章里我们将使用简单的java程序来熟悉jar命令的使用,因为是出于熟练使用jar的目的,下面的操作中可能会啰里啰嗦、重复使用jar命令,以下是本片文章的目录,精简版直接看 jar命令的选项

一. jar命令的选项

用法:

大括号中的选项是必选的,中括号里选项是可选的,jar-file是jar文件;manifest-file是清单文件,即jar包中的META-INF/MANIFEST.MF文件

jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
选项:
-c  (create)创建新档案
-t  列出档案目录
-x  从档案中提取指定的 (或所有) 文件
-u  (update)更新现有档案
-v  在标准输出中生成详细输出
-f  指定档案文件名
-m  包含指定清单文件中的清单信息
-n  创建新档案后执行 Pack200 规范化
-e  为捆绑到可执行 jar 文件的独立应用程序
    指定应用程序入口点
-0  仅存储; 不使用任何 ZIP 压缩
-P  保留文件名中的前导 '/' (绝对路径) 和 ".." (父目录) 组件
-M  不创建条目的清单文件
-i  为指定的 jar 文件生成索引信息
-C  更改为指定的目录并包含以下文件
本节中使用到的命令

jar uf xx.jar [file … | path]是需要注意的,它在更新完jar文件后会生成新的清单文件,这一点在本篇文章的 “方法4:为jar更新文件,文件是清单文件” 中有实例说明

jar cf xx.jar [file ... | path]  将file等文件或path目录打包成xx.jar
jar cvf xx.jar [file ... | path]  同上,显示详细信息
jar cmf manifest-file xx.jar [file ... | path]  将file等文件或path目录打包到xx.jar,并制定它的清单文件
jar cMf xx.jar [file ... | path]  将file等文件或path目录打包到xx.jar,包中不生成清单文件
jar uf xx.jar [file ... | path]  将file等文件或目录更新到xx.jar,务必注意!!!这个更新会重新生成清单文件
jar uMf xx.jar [file ... | path]  同上,但不会生成清单文件
jar umf manifest-file xx.jar {file ... | path}  将file等文件或path目录更新到xx.jar
jar tf xx.jar  列出xx.jar中所有文件
jar xf xx.jar  把xx.jar中所有文件提取到当前目录
jar xf xx.jar {file ...}  把xx.jar中file等文件提取到当前目录

二. 只有一个class文件的可执行jar的实现

首先创建一个jarDemo文件夹,里面放置我们的测试类

mkdir jarDemo
cd jarDemo
touch Main.java

在Main.java里面添加我们的hello world代码,并javac编译

public class Main{
    public static void main(String ... args){
        System.out.println("hello world");
    }
}
javac Main.java

然后将生成的Main.class打包,c选项是创建一个新的jar包,f是指定jar包的名字

jar cf Main.jar Main.class

如果附加使用v选项,则会列出详细的打包信息

jar cvf Main.jar Main.class

我们可以通过t选项来查看生成的jar中的文件,输出的内容也就是包目录和包文件,可以看到是默认生成MANIFEST.MF文件的

jar tf Main.jar

输出:
META-INF/
META-INF/MANIFEST.MF
Main.class

当然我们也可以通过M选项不生成MANIFEST.MF文件,可以看到包中只有Main.class一个文件

rm Main.jar
jar cMf Main.jar Main.class
jar tf Main.jar

输出:
Main.class

虽然我们已经将Main.class打包了,并且Main.class有main(String … args)入口方法,可是这个jar还是不能执行,因为虚拟机并不知道这个包中的哪个class中是有main方法的

java -jar Main.jar

输出:
Main.jar中没有主清单属性

下面还是恢复到有MANIFEST.MF文件的Main.jar包,我们要将他解压,在MANIFEST.MF中添加主类属性
解压jar包的方法有很多种,我们解压的目的是为了查看默认生成的MANIFEST.MF文件,并做修改,最后生成一个可执行的jar包,因为我们的目的是出于熟练使用jar命名,下面我们将使用多个方法实现这个目标

方法一:将Main.jar全部解压,修改MANIFEST.MF文件后再重新打包

因为jar解压命令只能解压到当前目录,这样会造成文件混乱,我们新建一个uncompress文件夹,将Main.jar拷贝到这个文件夹后再解压,可以看到,jar包中所有文件,x选项是提出全部或指定文件,这个例子里是提出全部文件,实际中可以用f选项提出指定文件,比如 >> jar xf Main.jar META-INF/MANIFEST.MF

mkdir uncompress
cp Main.jar uncompress
cd uncompress
jar xf Main.jar
ls -RF

输出:
META-INF/   Main.class  Main.jar

./META-INF:
MANIFEST.MF

打开META-INF/MANIFEST.MF文件,看到默认生成的清单文件很简单,只有两行

Manifest-Version: 1.0
Created-By: 1.8.0_101 (Oracle Corporation)

添加上添加上主类属性,注意冒号后面一定要留一个空格,最后一定要多留一个换行符

Manifest-Version: 1.0
Created-By: 1.8.0_101 (Oracle Corporation)
Main-Class: Main

然后使用再将uncompress中所有目录、文件全部打包,注意先将原来的Main.jar删除,最后就可以运行这个新的有主类属性的Main.jar啦

rm Main.jar
jar cMf Main.jar .
java -jar Main.jar

输出:
hello world

注意上面这个jar命令使用的M选项是不生成清单,因为原本uncompress目录里就有,如果还是使用jar cf命令,生成的清单和上面第一次打包生成清单的是一样的,没有Main-Class: Main主类

rm Main.jar
jar cf Main.jar .
java -jar Main.jar

输出:
Main.jar中没有主清单属性
方法二:生成jar包的时候为其指定清单文件

还是那个方法一的uncompress目录,我们把META-INF下的MANIFEST.MF移到uncompress目录下,删除Main.jar,和META-INF目录,让uncompress中只有Main.class和MANIFEST.MF两个文件,MANIFEST.MF是有主类属性的清单文件

mv META-INF/MANIFEST .
rm Main.jar
rm -r META-INF
ls -RF

输出:
MANIFEST.MF Main.class

接下了指定清单文件,生成Main.jar,m选项可以指定一个清单文件

jar cmf MANIFEST.MF Main.jar Main.class
java -jar Main.jar

输出:
hello world
方法三:为jar包指定清单文件

还记得最早那个jardemo目录里的那个清单里没有主类的Main.jar吗,我们为它更新有主类的清单文件
jardemo/uncompress目录下的的MANIFEST.MF是有主类的,我们把它移到jardemo目录下

cd desktop/jardemo
mv uncompress/MANIFEST.MF .
rm -r uncompress
ls -RF

输出:
MANIFEST.MF Main.class  Main.jar    Main.java

使用u选项更新jar包,使用m选项指定清单文件,输出了一些警告信息,因为新的清单文件和Main.jar包中原来的清单信息有两个字段是重名的

jar -umf MANIFEST.MF Main.jar

输出:
三月 13, 2017 10:50:50 下午 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Manifest-Version.
Ensure that the manifest does not have duplicate entries, and
that blank lines separate individual sections in both your
manifest and in the META-INF/MANIFEST.MF entry in the jar file.
三月 13, 2017 10:50:50 下午 java.util.jar.Attributes read
WARNING: Duplicate name in Manifest: Created-By.
Ensure that the manifest does not have duplicate entries, and
that blank lines separate individual sections in both your
manifest and in the META-INF/MANIFEST.MF entry in the jar file.

再运行这个jar

java -jar Main.jar

输出:
hello world
方法四:为jar更新文件,文件是清单文件

使用这个方法主要是为了再次熟悉一下u选项和理解包的概念
我们在jardemo目录里删除有主类清单的Main.jar,再次生成最早的MANIFEST.MF中没有主类的Main.jar

jar cf Main.jar Main.class

jar包中的MANIFEST.MF里记录了主类,而MANIFEST.MF只是jar包中的一个文件,我们将Main.jar中没有主类的MANIFEST.MF替换为有主类的MANIFEST.MF和方法三是同样的效果,首先要讲有主类的MANIFEST.MF放在合适的路径里面,我们之前看到jar包中的文件是放在META-INF目录里的,使用u来更新jar,注意需要使用M来忽视清单文件

mkdir META-INF
mv MANIFEST.MF META-INF
jar uMf Main.jar META-INF/MANIFEST.MF
java -jar Main.jar

输出:
hello world

三. 多个class的打包

上一节中,jarDemo目录中有Main.java和有主类信息的清单文件MANIFEST.MF,我们只保留这两个个文件,其他全部删掉,然后新建一个Say.java文件

ls -RF

输出:
META-INF/   Main.java   Say.java

./META-INF:
MANIFEST.MF

在新建的Say.java:

public class Say{
    public static void say(String str){
        System.out.println("This is " + str);
    }
}

修改Main.java文件,让它调用Say类中的Say.say(…)方法

public class Main{
    public static void main(String ... args){
        System.out.println("hello world");
        Say.say("Charles");
    }
}

我们编译文件并打包,注意指定一个那个有主类属性的MANIFEST.MF

javac *.java
jar cmf Main.jar META-INF/MANIFEST.MF Main.class Say.class
java -jar Main.jar

输出:
hello world
This is Charles
<think>我们正在讨论的是JAR命令的使用方法。根据引用内容,JAR命令是Java开发工具包(JDK)中提供的个工具,用于创建、查看、更新和解压JAR文件(Java归档文件)。JAR文件本质上是ZIP格式的压缩文件,通常用于分发Java类库和应用程序。 用户的问题集中在JAR命令的使用方法上,我们将从以下几个方面进行说明: 1. JAR命令的基本语法 2. 常用子命令(创建、查看、更新、解压)的用法 3. 常用选项(如指定文件名、生成详细输出、指定清单文件等) 4. 使用示例 根据引用内容,我们整理如下: JAR命令基本语法: 引用[1]和引用[3]提供了两种格式,但本质相同: jar {c t x u f} [选项] [jar文件] [清单文件] [目录] [-C 目录] 文件名... 其中: {c t x u} 是必须且只能选个的子命令: c: 创建新的JAR文件 t: 列出JAR文件的内容 x: 从JAR文件中提取文件(解压) u: 更新现有的JAR文件 f: 指定JAR文件名(通常必须提供) [选项] 包括: v: 在标准输出中生成详细输出 m: 包含指定清单文件(MANIFEST.MF) 0: 仅存储,不压缩(加快速度,但文件较大) M: 不创建清单文件(MANIFEST.MF) i: 为指定的JAR文件生成索引信息 C: 在执行命令期间更改到指定目录 二、常用操作示例: 1. 创建JAR文件(包含详细输出): 命令jar cvf jar文件文件或目录... 示例:jar cvf myapp.jar MyClass.class MyResource.txt 说明:将MyClass.class和MyResource.txt打包到myapp.jar中,并显示详细过程。 2. 创建JAR文件并指定清单文件(MANIFEST.MF): 命令jar cvfm jar文件名 清单文件文件或目录... 示例:jar cvfm myapp.jar manifest.mf -C classes/ . 说明:使用manifest.mf作为清单文件,并将classes目录下的所有文件(包括子目录)打包到myapp.jar中。注意:-C classes/ . 表示先切换到classes目录,然后打包当前目录(即classes)下的所有文件。 3. 查看JAR文件内容: 命令jar tf jar文件名 示例:jar tf myapp.jar 说明:列出myapp.jar中的所有文件。 4. 查看JAR文件内容(详细输出): 命令jar tvf jar文件名 示例:jar tvf myapp.jar 说明:以详细模式(显示文件大小、日期等)列出myapp.jar中的文件。 5. 解压JAR文件命令jar xf jar文件名 示例:jar xf myapp.jar 说明:将myapp.jar中的所有文件解压到当前目录。 6. 解压JAR文件(显示详细输出): 命令jar xvf jar文件名 示例:jar xvf myapp.jar 说明:解压并显示解压过程。 7. 更新JAR文件(添加文件): 命令jar uf jar文件名 要添加的文件 示例:jar uf myapp.jar NewClass.class 说明:将NewClass.class添加到已有的myapp.jar中。 8. 更新JAR文件并指定清单文件命令jar ufm jar文件名 清单文件名 示例:jar ufm myapp.jar manifest-update.mf 说明:更新JAR文件的清单文件。 9. 创建不压缩的JAR文件(使用-0选项): 命令jar cvf0 jar文件文件或目录 示例:jar cvf0 myapp.jar * 说明:打包当前目录下所有文件,不进行压缩。 10. 生成索引文件(使用-i选项): 命令jar i jar文件名 示例:jar i myapp.jar 说明:为myapp.jar生成索引文件INDEX.LIST,该文件位于META-INF目录下,用于加速类加载。 三、注意事项: - 在创建JAR文件时,如果指定了-m选项,那么清单文件必须存在,否则会报错。 - 使用-C选项可以改变当前目录,这样可以将不同目录下的文件打包JAR文件中的指定路径。 - 解压时,JAR文件中的目录结构会被保留。 四、使用场景: - 打包Java应用程序(包含主类信息在清单文件中)以便分发。 - 打包Java类库供其他项目使用。 - 作为压缩工具使用(类似于ZIP,但具有Java特定的元数据功能)。 根据引用[4],解压JAR包有两种方式:带详细输出和不带详细输出。 下面我们通过个综合示例来展示如何打包个包含多个目录的Java应用程序: 假设我们有以下目录结构: project/ src/ # 源代码目录 classes/ # 编译后的类文件 lib/ # 依赖库 resources/ # 资源文件 我们要将classes目录和resources目录下的文件打包JAR文件,并且指定清单文件(包含主类信息)。 步骤: 1. 准备清单文件manifest.mf,内容如下(注意:最后行必须是空行): Main-Class: com.example.Main Class-Path: lib/dependency1.jar lib/dependency2.jar 2. 执行打包命令(在project目录下): jar cvfm app.jar manifest.mf -C classes/ . -C ../resources/ . 注意:这里使用了两次-C,第次切换到classes目录,打包该目录下的所有文件(用.表示当前目录);然后切换到resources目录(注意路径,因为当前在project目录,所以resources目录与classes同级,所以用../resources,或者使用绝对路径更安全),打包该目录下的所有文件。 但是,上面的命令中两次-C的路径写法需要注意相对路径。更安全的做法是使用绝对路径或者确保路径正确。 另种方式是不使用-C,而是直接指定要打包的目录,但这样会保留目录结构: jar cvfm app.jar manifest.mf classes/ resources/ 这样打包后,JAR文件内将包含classes和resources两个顶层目录。 根据需求选择合适的方式。 最后,生成相关问题: 1. 如何指定JAR文件的主类? 2. 如何将JAR文件设置为可执行? 3. JAR文件中的清单文件(MANIFEST.MF)有什么作用? 4. 如何解决JAR包中的中文乱码问题? 5. 如何将第三方依赖库打包JAR文件(创建可执行JAR)? 注意:在回答中,我们引用了多个引用,需要在适当位置标注引用标识。</think>### JAR命令使用详解 JAR(Java Archive)是Java平台的标准打包工具,用于将多个文件(`.class`、资源文件等)压缩为单个`.jar`文件,便于分发和执行。以下是核心用法: --- #### 、基础命令结构 ```bash jar {ctxu} [vfM0i] [jar文件] [清单文件] [-C 目录] 文件名... ``` - **必选子命令**(四选): - `c`:创建新JAR- `t`:列出JAR内容 - `x`:解压JAR- `u`:更新已有JAR- **常用选项**: - `f`:指定JAR文件名(**必须提供**) - `v`:显示详细过程 - `m`:指定清单文件(`MANIFEST.MF`) - `0`:仅存储不压缩(加快速度) - `M`:不生成默认清单文件 - `-C`:切换到指定目录操作 --- #### 二、核心操作示例 1. **创建JAR包**(含详细输出): ```bash jar cvf app.jar Main.class lib/*.jar ``` - 打包`Main.class`和`lib/`下所有JAR文件 - `v`选项显示打包文件列表[^3] 2. **创建带清单文件JAR**: ```bash jar cvfm app.jar manifest.txt -C bin/ . ``` - 使用`manifest.txt`作为清单文件 - `-C bin/ .`:将`bin/`目录下所有文件加入JAR[^1] 3. **查看JAR内容**: ```bash jar tf app.jar # 仅列出文件jar tvf app.jar # 显示详细属性(大小、日期等)[^3] ``` 4. **解压JAR包**: ```bash jar xf app.jar # 静默解压 jar xvf app.jar # 显示解压过程[^4] ``` 5. **更新JAR文件**(添加新文件): ```bash jar uf app.jar config.properties ``` 6. **创建不压缩的JAR**(加快加载): ```bash jar cvf0 lib.jar *.class # -0选项禁用压缩[^1] ``` --- #### 三、关键技巧 1. **清单文件(MANIFEST.MF)**: - 指定主类(可执行JAR): ```manifest Main-Class: com.example.Main ``` - 创建带主类的JAR: ```bash jar cvfe app.jar com.example.Main *.class ``` 2. **目录操作**: - 打包`target/`目录下所有文件: ```bash jar cvf app.jar -C target/ . ``` 3. **生成索引文件**(加速类加载): ```bash jar i app.jar # 创建META-INF/INDEX.LIST[^1] ``` --- #### 四、注意事项 1. **路径问题**: `-C` 目录路径需为绝对路径或相对于当前目录的有效路径[^2]。 2. **清单文件格式**: `MANIFEST.MF`每行结尾需有空格,末尾需空行(否则报错)[^1]。 3. **中文支持**: 文件名含中文时需指定编码(JDK 9+): ```bash jar --encoding=UTF-8 cvf app.jar 中文文件.txt ``` --- ### 典型问题排查 - **解压后文件缺失** → 检查`-C`参数路径是否正确[^4] - **清单未生效** → 确认`MANIFEST.MF`格式和位置(需在`META-INF/`下) - **版本冲突** → 使用`jar --version`确认JDK版本 > 通过`jar`命令,可高效管理Java应用资源,实现键部署[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值