0%

深入理解Java中的Jar打包

前言

Jar包,是Java™ Archive的缩写,可以用这项技术把多个文件捆绑为一个文件,或者说,一种比较特殊的压缩技术。

Jar包提供了很多的好处:

  • 安全性:可以对jar包进行数字签名。
  • 减少下载时间:下载一个压缩包的速度肯定是比下载很多文件要快的多的。
  • 压缩:减少存储空间的消耗。
  • 扩展打包:扩展框架提供了一种向Java核心平台提供功能的方法。
  • 密封:所有的文件都被打包到了一起,所以可以强制版本统一。
  • 版本控制:jar包可以提供供应商和版本信息。
  • 可移植性:处理jar包是java的核心功能。

本博文主要翻译自java官方的tutorials,主要有四个部分,分别是简单使用jar包、manifest文件、签名和认证、使用相关api。

使用JAR文件:基础知识

jar包本质上其实就是通过zip文件格式进行打包的,标准情况下,Java Archive Tool是作为JDK的一部分提供的,而在日常中,我们使用的是jar命令。

创建jar包

用于创建 JAR 文件的命令的基本格式为:

1
jar cf jar-file input-file(s)

此命令中使用的选项和参数是:

  • c 选项表示你要 create (创建) 一个JAR文件。
  • f 选项表示你希望输出转到 file (文件) 而不是 stdout
  • jar-file 是你希望生成的 JAR 文件具有的名称。你可以使用任何文件名作为 JAR 文件。通常来说,JAR文件名的扩展名为 .jar,但这不是必需的。
  • input-file(s) 参数是一个以空格为分隔的列表,包含了需要打包在 JAR 文件中的一个或多个文件。input-file(s) 参数可以包含通配符 * 符号。如果是一个目录,则其中的内容会递归地加入到jar包中。

此命令将生成压缩的JAR文件并将其放在当前目录中。该命令还将为JAR存档生成默认清单文件。默认清单文件取名叫META-INF/MANIFEST.MF,里面只有最基本的JDK等信息。

除此之外,还可以有的选项是:

  • 选项描述v在构建 JAR 文件时,在 stdout 上生成 verbose (详细) 输出。详细输出告诉你添加到 JAR 文件中的每个文件的名称。
  • 0 (zero)表示你不希望压缩 JAR 文件。不压缩的话,最后打开的时候会比较快,因为不需要解压缩了,不过占用空间会比较大,看实际需要进行调整。
  • M表示不应生成默认清单文件。
  • m用于包括现有清单文件中的清单信息。使用此选项的格式为:jar cmf jar-file existing-manifest input-file(s)
  • C用于在打包的时候修改对应的结构。

注意jar包会存储创建文件的时间,所以多次创建jar包会有所不同。但是最好不要根据这点来作为版本控制信息,而是应该使用清单文件。

查看jar包

查看JAR文件内容的命令的基本格式是:

1
jar tf jar-file

让我们看看这个命令中使用的选项和参数:

  • t 选项表示你要查看 JAR 文件内容的 *table (表)*。
  • f 选项表示在命令行中指定了要查看其内容的 JAR 文件。
  • jar-file 参数是要查看其内容的 JAR 文件的路径和名称。

此命令将 JAR 文件的目录显示到 stdout

你可以选择添加详细选项 v,以在输出中生成有关文件大小和上次修改日期的其他信息。

解压jar包

用于提取 JAR 文件内容的基本命令是:

1
jar xf jar-file [archived-file(s)]

让我们看看这个命令中的选项和参数:

  • x 选项表示你要从 JAR 存档中 extract (提取) 文件。
  • f 选项表示要从中提取文件的 JAR file (文件) 是在命令行中指定的,而不是通过 stdin 指定的。
  • jar-file 参数是从中提取文件的 JAR 文件的文件名(或路径和文件名)。
  • archived-file(s) 是一个可选参数,由要从存档中提取的文件的空格分隔列表组成。如果此参数不存在,Jar 工具将提取存档中的所有文件。

注解,当解压缩的时候,解压出来如果和当前文件有同名的情况,会覆盖掉原来的文件。

更新jar包

没啥用,基本上重新打一个就行了…

JAR文件作为应用程序

你可以使用 Java 启动程序(java 命令)运行 JAR 打包的应用程序。基本命令是:

1
java -jar jar-file

-jar 标志告诉启动程序应用程序是以 JAR 文件格式打包的。你只能指定一个 JAR 文件,该文件必须包含所有特定于应用程序的代码。

在执行此命令之前,请确保运行时环境具有有关 JAR 文件中哪个类是应用程序入口点的信息。

要指示哪个类是应用程序的入口点,必须将 Main-Class 头添加到 JAR 文件的清单中。头采用以下形式:

1
Main-Class: classname

头的值 classname 是作为应用程序入口点的类的名称。

在清单文件中设置 Main-Class 时,可以从命令行运行应用程序:

1
java -jar app.jar

总结

jar包本质上就是一个压缩包,所以如果你很熟练tar命令,其实jar命令就是手到擒来的事情。

使用清单文件:基础知识

之前提到jar包的很多功能,比如电子签名、版本控制之类的,这些就是通过清单文件(manifest)文件来实现的。

默认清单

创建jar包的时候,如果没有指定清单,那么系统会自动创建一个叫META-INF/MANIFEST.MF的清单。在jar包中,有且仅能有一个清单文件,而且名字必须是这个。

修改清单文件

在创建jar包的时候,可以通过m选项自己指定一个清单文件。注意,你自己准备的清单文件(不用在意叫什么,最后都会被强制改名的),必须以新行或回车符结束,否则会出现无法解析最后一行的问题。具体的格式是这样子的:jar cfm jar-file manifest-addition input-file(s),注意mf 选项的顺序必须与相应的参数相同。

  • c 选项表示你要 create (创建) 一个 JAR 文件。
  • m 选项表示你要将现有文件中的信息合并到正在创建的 JAR 文件的清单文件中。
  • f 选项表示你希望输出转到 file (文件)(你正在创建的 JAR 文件)而不是标准输出。
  • manifest-addition 是现有文本文件的名称(或路径和名称),其内容要添加到 JAR 文件清单的内容中。
  • jar-file 是你希望生成的 JAR 文件具有的名称。
  • input-file(s) 参数是一个以空格分隔的列表,其中包含要放置在 JAR 文件中的一个或多个文件。

设置入口点

jar包中需要通过指定哪个启动程序,可以通过Main-Class: classname进行指定,这样通过java -jar xxx.jar就可以启动对应的类了。

将类添加到 JAR 文件的类路径中

简单来说就是一个jar包引用另外一个jar包中的文件,那么可以直接在其的清单文件中直接指定Class-Path: jar1-name jar2-name directory-name/jar3-name

设置包版本信息

你可能需要在 JAR 文件的清单中包含软件包版本信息。你使用清单中的以下头提供此信息:

定义
Name 规范的名称。
Specification-Title 规范的标题。
Specification-Version 规范的版本。
Specification-Vendor 规范的供应商。
Implementation-Title 实现的标题。
Implementation-Version 实现的内部版本号。
Implementation-Vendor 实现的供应商。

不过大概是接触不到的。