得益于Ant、Maven等构建工具的强大功能,我们无需每天冗繁的手动通过jar
命令来打包Java class和资源文件,软件的日常打包部署通常都交给它们处理了。不过最近遇到点构建的问题,查了JAR相关的一些文章。在此做一个总结,对JAR有兴趣的朋友可以一看。
什么是JAR
JAR全称为Java Archive,zip格式的Java打包文件。目的是用来把class文件,资源文件打包成一个文件,利于部署,发布,以及传输。除了打包功能,它被用来构建应用组件(Application Blocks),构建Java扩展(Extension)。此外还包含一个可选的META-INFO目录,可以用来存储版本(Version),安全(Security, signer),索引(Index),服务(Services)等信息。JAR可以通过的jar命令或者java.util.jar API生成。
JAR的常用命令
- 打包一个或者多个文件
jar cvf example.jar class1.class class2.class
- 打包文件夹
jar cvf example.jar -C build/ .
- 查看JAR的目录(内容)
jar tf example.jar
- 解压JAR文件
jar xf example.jar
- 运行可执行的JAR文件
jar -jar example.jar
- 为JAR文件添加索引
jar i exaple.jar
- 指定MANIFEST.MF打包
jar cvfm example.jar MyMANIFEST.MF -C build/ .
可选META-INFO文件夹的格式说明
JAR包含一个可选的META-INF,不过JAR与ZIP的区别正在于此。所有的配置信息都存于该目录。主要包括以下一些文件以及文件夹:
- MANIFEST.MF
最重要的的配置文件,存储版本,创建者,包等信息。 - INDEX.LIST
JAR的索引信息,加快JVM搜索和加载class的速度,可选,通过i
可选项产生。 - key.SF和key.DSA
key.SF为签名文件,key.DSA为key.SF对应的加密数据块(二进制数据,以base64编码存储),key为keytool生成的key的名称。 - services文件夹
存储Service Provider的配置信息
了解MANIFEST.MF
由一个主区以及不限数目的个性化区(Section)组成。个性化区可以覆盖主区的值。所有的配置信息都是键值对(Key:Value),区之间用空行隔开。
主区(Main Section)属性:
- Manifest-Version
版本号,如1.0.0
- Create-By
创建者,如1.6.0_35 (Sun Microsystems Inc.)
- Class-Path
JVM搜索class的路径,值得强调的是默认为相对路径,并且环境变量以及命令行参数传入的class-path无效了,被覆盖(Override)了。多个 lib之间用空格隔开。如lib/slf4j-api-1.6.4.jar lib/log4j-1.2.16.jar
- Main-Class
可执行JAR包的入口类名,含包名。如com.example.Start
个性化区(Individual Section)属性:
个性化区域都以Name:开始,标记配置的时哪一个文件或者文件夹。比如: Name: com.example.Start
。除了主区的属性外还包括:
- Sealed
Sealed: true
表示所有package内的class都需要在当前JAR包找到。 - Content-Type
文件类型,格式为type/subtype,如image/bmp
- Java-Bean
标识某个class是否是Java Bean,值为true或者false。
签名的JAR文件
通过给JAR文件签名,可以验证JAR文件是否被篡改过。一个被签名的JAR与签名之前相比,MANIFEST.MF文件会新增一些记录,另外还会新增两个文件,加密清单文件key.SF和加密数据块文件key.DSA。加密的步骤如下:
- 在Java的keystore里面生成key,testkey为key的名称,testpass为key的密码,teststore为keystore的名称,teststorepass为keystore的密码。 如果keystore不存在,会自动生成。
-validity 360
表示有效期为365天。
keytool -genkey -alias testkey -keypass testpass -validity 365 -keystore teststore -storepass teststorepass
- 给一个已经存在的JAR文件example.jar签名,用上一个步骤中的testkey作为密码。签名之后的JAR文件为Sexample.jar。
jarsigner -keystore teststore -storepass teststorepass -keypass testpass -signedjar Sexample.jar example.jar testkey
- 验证签名JAR文件
jarsigner -verify Sexample.jar