jar包
# jar包
jar包:Java类的压缩包
# 引出jar包的概念
如果我们想让同事使用我们的编写的类,可以怎么做呢?
比如,我们写了一个工具类,可以通过发送单个文件的方式,给到同事;
但如果我们写了多个类呢?并且每个类是按包存储的,一个个文件发给同事,太麻烦了,我们可以打个压缩包给到同事,同事拿到后再解压到对应的目录…………
在一个大型项目中,这样就有点不可取了。因为我们一个项目可能有很多很多的工具类,可能多达几十个,传统的文件管理太麻烦了:
- 需要记住每个工具类的路径,然后import;
- 依赖于具体操作系统的文件系统。当需要迁移到其他操作系统的时候,需要重新压缩包和传输;
- 更新问题:当工具类有更新,就需要重新解压到特定的文件夹。。。。
因此,Java提供了一种文件格式,可以将工具类压缩后,不解压也能使用里面的类(包括import和使用里面的方法),这种文件格式就jar包,是一种以 .jar
后缀结尾的文件。
我们可以进入C:\Program Files\Java\jdk1.8.0_281\jre\lib (笔者安装到了C盘,请读者自行更换自己的Java安装目录),可以看到有不少jar包:
C:\Program Files\Java\jdk1.8.0_281\jre\lib
我们复制一份其中的rt.jar包到其他目录,并修改文件后缀名为 .zip,然后打开:
可以看到里面有很多的class类,这些就是Java提供给我们使用的类。
我们也可以自己生成一个jar包,提供给其他人使用,好处如下:
- 这样别人只需用我们的jar包,不用解压,
- 当需要迁移到其他操作系统的时候直接挪到jar包即可;
- 当版本有更新的时候只需更换jar包;
- 各个工具类直接是独立的jar包,不会互相混杂
- …………
# 生成一个jar包
按照Java的规范,一般类都是用包来组织的。我们按域名的结构新建目录,并定义一个类:
D:\>md com\peterjxl //Windows下
mkdir com/peterjxl //Linux下
2
package com.peterjxl;
public class Hello{
public static void main(String[] args) {
System.out.println("Hello Jar");
}
}
2
3
4
5
6
7
然后编译生成class文件,因为我们最后是用到class文件的
D:\> javac com/peterjxl/Hello.java
因为jar包就是zip包,所以,直接在资源管理器中,找到正确的目录,点击右键,在弹出的快捷菜单中选择“发送到”,“压缩(zipped)文件夹”,就制作了一个zip文件。然后,把后缀从.zip
改为.jar
,一个jar包就创建成功。当然,也可以用命令行创建
我们这里命名为MyJar.jar
# 使用一个jar包
我们要引用jar包里的类,只需在编译和运行的时候,指定classpath即可
我们在D盘新建一个Main.java,里面引入Hello类。
import com.peterjxl.Hello;
public class Main{
public static void main(String[] args) {
Hello o = new Hello();
o.main(null);
}
}
2
3
4
5
6
7
8
我们编译和运行:(注意,运行和编译前先删除之前我们新建的java文件)
D:\> javac -cp Myjar.jar Main.java
D:\> java -cp "Myjar.jar;." Main
Hello Jar
2
3
如果要使用多个jar包, 则 jar包之间用分号 ; 分割,例如:
C:\dependency\framework.jar:C:\location\otherFramework.jar
# 运行一个jar包
jar包还可以包含一个特殊的/META-INF/MANIFEST.MF
文件,MANIFEST.MF
是纯文本,可以指定Main-Class
和其它信息。JVM会自动读取这个MANIFEST.MF
文件,如果存在Main-Class
,我们就不必在命令行指定启动的类名,而是用更方便的命令:
java -jar hello.jar
我们来尝试下。我们先解压之前的jar包,在里面新建一个/META-INF/MANIFEST.MF
文件,里面存放的内容如下:
Main-Class: com.peterjxl.Hello
2
注意:
- Main-Class: 后面要空一格,再写上完整类名。
- 最下面一行是一行空行,不然会报错
MyJar.jar中没有主清单属性
。如果没有Main-Class也会报这个错 - 更多信息,可以参考官方文档:Working with Manifest Files: The Basics (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files) (opens new window)
# 其他方式创建jar包
除了自己手工生成压缩包之外,Java还提供了命令行给我们调用,使得我们可以在命令行里创建jar包。
表 1. 常见的 jar 工具用法
功能 | 命令格式 | 举例 |
---|---|---|
用一个单独的文件创建一个 JAR 文件 | jar cf jar-file file-name | |
用一个单独的文件创建一个 JAR 文件,并显示压缩过程 | jar cvf test.jar test | |
用一个目录创建一个 JAR 文件 | jar cf jar-file dir-name | jar cf Myjar.jar com |
创建一个未压缩的 JAR 文件 | jar cf0 jar-file dir-name | |
更新一个 JAR 文件 | jar uf jar-file input-file... | |
查看一个 JAR 文件的内容 | jar tf jar-file | |
提取一个 JAR 文件的内容 | jar xf jar-file | |
从一个 JAR 文件中提取特定的文件 | jar xf jar-file archived-file... | |
运行一个打包为可执行 JAR 文件的应用程序 | java -jar app.jar |
我们试着创建一个jar包,并用-e选项指定程序入口的主类名(记得先删除之前的我们手工压缩改后缀名的jar包)
D:\> jar cvfe Myjar.jar com.peterjxl.Hello com
已添加清单
正在添加: com/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: com/peterjxl/(输入 = 0) (输出 = 0)(存储了 0%)
正在添加: com/peterjxl/Hello.class(输入 = 426) (输出 = 293)(压缩了 31%)
正在添加: com/peterjxl/Hello.java(输入 = 130) (输出 = 118)(压缩了 9%)
2
3
4
5
6
用压缩文件打开jar包,可以看到里面默认有MANIFEST.MF
文件,不用我们自己生成了,方便了很多。
我们看看运行正不正常:
D:\> java -jar Myjar.jar
Hello Jar
2
其他命令不一一试了,读者了解即可。
一般情况下,IDE也提供了创建jar包的方法,不同IDE的操作方法不同,这里不详细展开了。
# 小结
使用jar包的好处,专业一点的说法如下:
- 安全,可以对其进行数字签名,只让能够识别数字签名的用户使用里面的东西。
- 加快下载速度;
- 压缩,使文件变小,与ZIP压缩机制完全相同。
- 包封装。能够让JAR包里面的文件依赖于统一版本的类文件。
- 可移植性,能够在各种平台上直接使用。
- 把一个JAR文件添加到系统的classpath环境变量之后,java通常会把这个JAR文件当做一个路径来处理。通常使用jar命令来压缩,可以把一个或多个路径全部压缩成一个JAR文件。
在IDE中运行Java程序,IDE自动传入的-cp
参数是当前工程的bin
目录和引入的jar包,无需使用这么复杂的命令。
本文涉及到的代码:
Gitee:01.JavaSE/05.OOP/07.jarLearn · 小林/LearnJava - 码云 - 开源中国 (opens new window)
GitHub:LearnJava/01.JavaSE/05.OOP at master · Peter-JXL/LearnJava (opens new window)