classpath和jar
1. classpath
什么是classpath
在Java中,我们经常听到classpath
这个东西。到底什么是classpath
?
classpath
是JVM用到的一个环境变量,指类路径,即它用来指示JVM如何寻找class
。也就是说,JVM需要知道,如果要加载一个com.exmaple.Hello
的类,应该去哪搜索对应的Hello.class
文件。
所以,classpath
就是一组目录的集合,它设置的搜索路径与操作系统相关。例如,
在Windows系统上,用
;
分隔,带空格的目录用""
括起来,可能长这样:C:\work\project1\bin;C:\shared;"D:\My Documents\project1\bin"
在Linux系统上,用
:
分隔,可能长这样:/usr/shared:/usr/local/bin:/home/liaoxuefeng/bin
现在我们假设classpath
是.;D:\work\project1\bin;C:\shared
,当JVM在加载com.exmaple.Hello
这个类时,会依次查找:
<当前目录>\com\exmaple\Hello
D:\work\project1\bin\com\exmaple\Hello
C:\shared\com\exmaple\Hello
如果JVM在某个路径下找到了对应的class
文件,就不再往后继续搜索。如果所有路径下都没有找到,就报错。
如何设定classpath
classpath
的设定方法有两种:
- 在系统环境变量中设置
classpath
环境变量,不推荐; - 在启动JVM时设置
classpath
变量,推荐。
我们强烈不推荐在系统环境变量中设置classpath
,那样会污染整个系统环境。在启动JVM时设置classpath
才是推荐的做法。实际上就是给java
命令传入-classpath
或-cp
参数:
java -classpath .;D:\work\project1\bin;C:\shared com.exmaple.Hello
或者使用-cp
的简写:
java -cp .;C:\work\project1\bin;C:\shared com.exmaple.Hello
如果没有设置classpath
的系统环境变量,也没有传入-cp
参数,那么JVM默认的classpath
为.
,即当前目录:
java com.exmaple.Hello
这意味着上述命令告诉JVM只在当前目录搜索Hello.class
。
2. jar
2.1 jar 文件
jar 文件的全称为 Java Archive File,意思为 Java 档案文件。
jar 文件使用 ZIP 格式组织文件和子目录,可以使用任何 ZIP 工具查看 JAR 文件,通常也称其为jar 包。jar 文件与 ZIP 文件的区别就是在 jar 文件中默认包含了一个名为 META-INF/MANIFEST.MF
的清单文件,这个清单文件是在生成 jar 文件时由系统自动创建的。
使用 JAR 文件有以下好处:
- 安全:能够对 JAR 文件进行数字签名,只让能够识别数字签名的用户使用里面的东西;
- 加快下载速度:在网上使用 Applet 时,如果存在多个文件而不打包,为了能够把每个文件都下载到客户端,需要为每个文件单独建立一个 HTTP 连接,这是非常耗时的工作。将这些文件压缩成一个 JAR 包,只要建立一次 HTTP 连接就能够一次下载所有的文件。
- 压缩:使文件变小,JAR 的压缩机制和 ZIP 完全相同;
- 包封装:能够让 JAR 包里面的文件依赖于统一版本的类文件;
- 可移值性:JAR 包作为内嵌在 Java 平台内部处理的标准,能够在各种平台上直接使用。
当一个应用程序开发成功后,大致有如下三种发布方式:
使用平台相关的编译器将整个应用编译成平台相关的可执行性文件;
为应用编辑一个批处理文件;
将一个应用程序制作成可执行的 jar 包,通过 jar 包来发布应用程序:
如果开发者把整个应用制作成一个可执行的 jar 包交给用户,那么用户使用起来就方便了。在 Windows 下安装 JRE 时,安装文件会将*.jar 文件映射成由 javaw.exe 打开,对于一个可执行的 jar 包,用户只需要双击它就可以运行程序了,和阅读*.chm 文档一样方便(*.chm 文档默认是由 hh.exe 打开的)。
创建可执行的 jar 包的关键在于:让 javaw 命令知道 jar 包中哪个类是主类,javaw 命令可以通过运行该主类来运行程序。
jar 命令有
-e
选项即可指定 jar 包中作为程序入口的主类的类名,故而制作一个可执行的 jar 包只要增加-e
选项即可:// test.Test是完整类名 jar cvfe test.jar test.Test test
运行 jar 包有两种方式:
- 使用 java 命令:
java -jar test.jar
- 使用 javaw 命令:
javaw test.jar
- 使用 java 命令:
2.2 jar 命令
JAR 文件通常使用 jar 命令压缩而成,当使用 jar 命令压缩生成 jar 文件时,可以把一个或多个路径全部压缩成一个 JAR 文件。jar 是随 JDK 自动安装的,在 JDK 安装目录下的 bin 目录中,Windows 下文件名为 jar.exe,Linux 下文件名为 jar。


语法:通常 jar 命令的格式为jar options file1, file2…
选项 | 说明 |
---|---|
c | 创建一个新的或者空的存档文件并加入文件。若指定的文件名是目录,jar 程序将会对它们进行递归处理 |
C | 暂时改变目录,如 jar cvf jarFileName.jar -C classes *.class 改变 classes 子目录,以便增加这些类文件 |
e | 在清单文件中创建一个条目 |
f | 将 jar 文件名指定为第二个命令行参数。如果没有这个参数,jar 命令会将结果写到标准输出上(在创建 jar 文件时),或者从标准输入中读取它(在解压或者列出 jar 文件内容时) |
i | 建立索引文件,用于加快对大型归档的查找 |
m | 将一个清单文件(manifest)添加到 jar 文件中,清单是对存档内容和来源的说明。每个归档都有一个默认的清单文件。 |
M | 不为条目创建清单文件 |
t | 显示内容表 |
u | 更新一个已有的 jar 文件 |
v | 生成详细的输出结果 |
x | 解压文件。如果提供一个或多个文件名,只解压这些文件;否则,解压所有文件 |
0 | 存储,不进行 ZIP 压缩 |
2.3 清单文件
除了类文件、图像和其他资源外,每个JAR文件还包含一个清单文件(manifest),用于描述归档文件的特殊特性。
清单文件被命名为MANIFEST.MF
,位于JAR文件的一个特殊的META-INF
子目录中。符合标准的最小清单文件极其简单:
Manifest-Version: 1.0
复杂的清单文件可能包含更多条目。这些清单条目被分成多个节,节与节之间用空行分开。第一节被称为主节,它作用于整个JAR文件。随后的条目用来指定命名实体的属性,如单个文件、包或URL,它们都必须以一个Name条目开始。如:
Manifest-Version: 1.0
lines describing this archive.
Name: Woozle.class
lines describing this file
Name: com/mycompany/mypkg
lines describing this package
清单文件的最后一行必须以换行符结束。
2.4 可执行 JAR 文件
可使用jar命令当中的e选项指定程序的入口点,即通常需要在调用java程序启动器时指定的类:
jar cvfe myProgram.jar com.mycompany.mypkg.MainAppClass files to add
或者,可以在清单文件中指定程序的,包括以下形式的语句(不要为主类名增加扩展名.class):
Main-Class: com.mycompany.mypkg.MainAppClass
不论使用哪一种方法,用户可以简单地通过下面的命令来启动程序:
java -jar MyProgram.jar
2.5 多版本JAR
Java9引入了多版本JAR,其中可以包含面向不同Java版本的类文件。
暂略。