JAR 文件揭密.docx
- 文档编号:5961194
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:9
- 大小:21.61KB
JAR 文件揭密.docx
《JAR 文件揭密.docx》由会员分享,可在线阅读,更多相关《JAR 文件揭密.docx(9页珍藏版)》请在冰豆网上搜索。
JAR文件揭密
JAR文件揭密
探索JAR文件格式的强大功能
文档选项
将此页作为电子邮件发送
级别:
初级
PagadalaJ.Suresh(pjsuresh@),软件工程师,IBMGlobalServicesIndia
PalaniyappanThiagarajan(tpalaniy@),软件工程师,IBMGlobalServicesIndia
2003年11月15日
大多数Java程序员都熟悉对JAR文件的基本操作。
但是只有少数程序员了解JAR文件格式的强大功能。
在本文中,作者探讨了JAR格式的许多功能和优势,包括打包、可执行的JAR文件、安全性和索引。
JAR文件是什么?
JAR文件格式以流行的ZIP文件格式为基础,用于将许多个文件聚集为一个文件。
与ZIP文件不同的是,JAR文件不仅用于压缩和发布,而且还用于部署和封装库、组件和插件程序,并可被像编译器和JVM这样的工具直接使用。
在JAR中包含特殊的文件,如manifests和部署描述符,用来指示工具如何处理特定的JAR。
一个JAR文件可以用于:
用于发布和使用类库
作为应用程序和扩展的构建单元
作为组件、applet或者插件程序的部署单位
用于打包与组件相关联的辅助资源
JAR文件格式提供了许多优势和功能,其中很多是传统的压缩格式如ZIP或者TAR所没有提供的。
它们包括:
安全性。
可以对JAR文件内容加上数字化签名。
这样,能够识别签名的工具就可以有选择地为您授予软件安全特权,这是其他文件做不到的,它还可以检测代码是否被篡改过。
减少下载时间。
如果一个applet捆绑到一个JAR文件中,那么浏览器就可以在一个HTTP事务中下载这个applet的类文件和相关的资源,而不是对每一个文件打开一个新连接。
压缩。
JAR格式允许您压缩文件以提高存储效率。
传输平台扩展。
Java扩展框架(JavaExtensionsFramework)提供了向Java核心平台添加功能的方法,这些扩展是用JAR文件打包的(Java3D和JavaMail就是由Sun开发的扩展例子)。
包密封。
存储在JAR文件中的包可以选择进行密封,以增强版本一致性和安全性。
密封一个包意味着包中的所有类都必须在同一JAR文件中找到。
包版本控制。
一个JAR文件可以包含有关它所包含的文件的数据,如厂商和版本信息。
可移植性。
处理JAR文件的机制是Java平台核心API的标准部分。
压缩的和未压缩的JAR
jar工具(有关细节参阅jar工具)在默认情况下压缩文件。
未压缩的JAR文件一般可以比压缩过的JAR文件更快地装载,因为在装载过程中要解压缩文件,但是未压缩的文件在网络上的下载时间可能更长。
META-INF目录
大多数JAR文件包含一个META-INF目录,它用于存储包和扩展的配置数据,如安全性和版本信息。
Java2平台识别并解释META-INF目录中的下述文件和目录,以便配置应用程序、扩展和类装载器:
MANIFEST.MF。
这个manifest文件定义了与扩展和包相关的数据。
INDEX.LIST。
这个文件由jar工具的新选项-i生成,它包含在应用程序或者扩展中定义的包的位置信息。
它是JarIndex实现的一部分,并由类装载器用于加速类装载过程。
xxx.SF。
这是JAR文件的签名文件。
占位符xxx标识了签名者。
xxx.DSA。
与签名文件相关联的签名程序块文件,它存储了用于签名JAR文件的公共签名。
jar工具
为了用JAR文件执行基本的任务,要使用作为JavaDevelopmentKit的一部分提供的JavaArchiveTool(jar工具)。
用jar命令调用jar工具。
表1显示了一些常见的应用:
表1.常见的jar工具用法
功能命令
用一个单独的文件创建一个JAR文件jarcfjar-fileinput-file...
用一个目录创建一个JAR文件jarcfjar-filedir-name
创建一个未压缩的JAR文件jarcf0jar-filedir-name
更新一个JAR文件jarufjar-fileinput-file...
查看一个JAR文件的内容jartfjar-file
提取一个JAR文件的内容jarxfjar-file
从一个JAR文件中提取特定的文件jarxfjar-filearchived-file...
运行一个打包为可执行JAR文件的应用程序java-jarapp.jar
回页首
可执行的JAR
一个可执行的jar文件是一个自包含的Java应用程序,它存储在特别配置的JAR文件中,可以由JVM直接执行它而无需事先提取文件或者设置类路径。
要运行存储在非可执行的JAR中的应用程序,必须将它加入到您的类路径中,并用名字调用应用程序的主类。
但是使用可执行的JAR文件,我们可以不用提取它或者知道主要入口点就可以运行一个应用程序。
可执行JAR有助于方便发布和执行Java应用程序。
创建可执行JAR
创建一个可执行JAR很容易。
首先将所有应用程序代码放到一个目录中。
假设应用程序中的主类是com.mycompany.myapp.Sample。
您要创建一个包含应用程序代码的JAR文件并标识出主类。
为此,在某个位置(不是在应用程序目录中)创建一个名为manifest的文件,并在其中加入以下一行:
Main-Class:
com.mycompany.myapp.Sample
然后,像这样创建JAR文件:
jarcmfmanifestExecutableJar.jarapplication-dir
所要做的就是这些了--现在可以用java-jar执行这个JAR文件ExecutableJar.jar。
一个可执行的JAR必须通过menifest文件的头引用它所需要的所有其他从属JAR。
如果使用了-jar选项,那么环境变量CLASSPATH和在命令行中指定的所有类路径都被JVM所忽略。
启动可执行JAR
既然我们已经将自己的应用程序打包到了一个名为ExecutableJar.jar的可执行JAR中了,那么我们就可以用下面的命令直接从文件启动这个应用程序:
java-jarExecutableJar.jar
回页首
包密封
密封JAR文件中的一个包意味着在这个包中定义的所有类都必须在同一个JAR文件中找到。
这使包的作者可以增强打包类之间的版本一致性。
密封还提供了防止代码篡改的手段。
要密封包,需要在JAR的manifest文件中为包添加一个Name头,然后加上值为“true”的Sealed头。
与可执行的JAR一样,可以在创建JAR时,通过指定一个具有适当头元素的manifest文件密封一个JAR,如下所示:
Name:
com/samplePackage/
Sealed:
true
Name头标识出包的相对路径名。
它以一个“/”结束以与文件名区别。
在Name头后面第一个空行之前的所有头都作用于在Name头中指定的文件或者包。
在上述例子中,因为Sealed头出现在Name头后并且中间没有空行,所以Sealed头将被解释为只应用到包com/samplePackage上。
如果试图从密封包所在的JAR文件以外的其他地方装载密封包中的一个类,那么JVM将抛出一个SecurityException。
扩展打包
扩展为Java平台增加了功能,在JAR文件格式中已经加入了扩展机制。
扩展机制使得JAR文件可以通过manifest文件中的Class-Path头指定所需要的其他JAR文件。
假设extension1.jar和extension2.jar是同一个目录中的两个JAR文件,extension1.jar的manifest文件包含以下头:
Class-Path:
extension2.jar
这个头表明extension2.jar中的类是extension1.jar中的类的扩展类。
extension1.jar中的类可以调用extension2.jar中的类,并且不要求extension2.jar处在类路径中。
在装载使用扩展机制的JAR时,JVM会高效而自动地将在Class-Path头中引用的JAR添加到类路径中。
不过,扩展JAR路径被解释为相对路径,所以一般来说,扩展JAR必须存储在引用它的JAR所在的同一目录中。
例如,假设类ExtensionClient引用了类ExtensionDemo,它捆绑在一个名为ExtensionClient.jar的JAR文件中,而类ExtensionDemo则捆绑在ExtensionDemo.jar中。
为了使ExtensionDemo.jar可以成为扩展,必须将ExtensionDemo.jar列在ExtensionClient.jar的manifest的Class-Path头中,如下所示:
Manifest-Version:
1.0
Class-Path:
ExtensionDemo.jar
在这个manifest中Class-Path头的值是没有指定路径的ExtensionDemo.jar,表明ExtensionDemo.jar与ExtensionClientJAR文件处在同一目录中。
回页首
JAR文件中的安全性
JAR文件可以用jarsigner工具或者直接通过java.securityAPI签名。
一个签名的JAR文件与原来的JAR文件完全相同,只是更新了它的manifest,并在META-INF目录中增加了两个文件,一个签名文件和一个签名块文件。
JAR文件是用一个存储在Keystore数据库中的证书签名的。
存储在keystore中的证书有密码保护,必须向jarsigner工具提供这个密码才能对JAR文件签名。
图1.Keystore数据库
JAR的每一位签名者都由在JAR文件的META-INF目录中的一个具有.SF扩展名的签名文件表示。
这个文件的格式类似于manifest文件--一组RFC-822头。
如下所示,它的组成包括一个主要部分,它包括了由签名者提供的信息、但是不特别针对任何特定的JAR文件项,还有一系列的单独的项,这些项也必须包含在menifest文件中。
在验证一个签名的JAR时,将签名文件的摘要值与对JAR文件中的相应项计算的摘要值进行比较。
清单1.签名JAR中的Manifest和signature文件
ContentsofsignaturefileMETA-INF/MANIFEST.MF
Manifest-Version:
1.0
Created-By:
1.3.0(SunMicrosystemsInc.)
Name:
Sample.java
SHA1-Digest:
3+DdYW8INICtyG8ZarHlFxX0W6g=
Name:
Sample.class
SHA1-Digest:
YJ5yQHBZBJ3SsTNcHJFqUkfWEmI=
ContentsofsignaturefileMETA-INF/JAMES.SF
Signature-Version:
1.0
SHA1-Digest-Manifest:
HBstZOJBuuTJ6QMIdB90T8sjaOM=
Created-By:
1.3.0(SunMicrosystemsInc.)
Name:
Sample.java
SHA1-Digest:
qipMDrkurQcKwnyIlI3Jtrnia8Q=
Name:
Sample.class
SHA1-Digest:
pT2DYby8QXPcCzv2NwpLxd8p4G4=
数字签名
一个数字签名是.SF签名文件的已签名版本。
数字签名文件是二进制文件,并且与.SF文件有相同的文件名,但是扩展名不同。
根据数字签名的类型--RSA、DSA或者PGP--以及用于签名JAR的证书类型而有不同的扩展名。
Keystore
要签名一个JAR文件,必须首先有一个私钥。
私钥及其相关的公钥证书存储在名为keystores的、有密码保护的数据库中。
JDK包含创建和修改keystores的工具。
keystore中的每一个密钥都可以用一个别名标识,它通常是拥有这个密钥的签名者的名字。
所有keystore项(密钥和信任的证书项)都是用唯一别名访问的。
别名是在用keytool-genkey命令生成密钥对(公钥和私钥)并在keystore中添加项时指定的。
之后的keytool命令必须使用同样的别名引用这一项。
例如,要用别名“james”生成一个新的公钥/私钥对并将公钥包装到自签名的证书中,要使用下述命令:
keytool-genkey-aliasjames-keypassjamespass
-validity80-keystorejamesKeyStore
-storepassjamesKeyStorePass
这个命令序列指定了一个初始密码“jamespass”,后续的命令在访问keystore“jamesKeyStore”中与别名“james”相关联的私钥时,就需要这个密码。
如果keystore“jamesKeyStore”不存在,则keytool会自动创建它。
jarsigner工具
jarsigner工具使用keystore生成或者验证JAR文件的数字签名。
假设像上述例子那样创建了keystore“jamesKeyStore”,并且它包含一个别名为“james”的密钥,可以用下面的命令签名一个JAR文件:
jarsigner-keystorejamesKeyStore-storepassjamesKeyStorePass
-keypassjamespass-signedjarSSample.jarSample.jarjames
这个命令用密码“jamesKeyStorePass”从名为“jamesKeyStore”的keystore中提出别名为“james”、密码为“jamespass”的密钥,并对Sample.jar文件签名、创建一个签名的JAR--SSample.jar。
jarsigner工具还可以验证一个签名的JAR文件,这种操作比签名JAR文件要简单得多,只需执行以下命令:
jarsigner-verifySSample.jar
如果签名的JAR文件没有被篡改过,那么jarsigner工具就会告诉您JAR通过验证了。
否则,它会抛出一个SecurityException,表明哪些文件没有通过验证。
还可以用java.util.jar和java.securityAPI以编程方式签名JAR(有关细节参阅参考资料)。
也可以使用像NetscapeObjectSigningTool这样的工具。
回页首
JAR索引
如果一个应用程序或者applet捆绑到多个JAR文件中,那么类装载器就使用一个简单的线性搜索算法搜索类路径中的每一个元素,这使类装载器可能要下载并打开许多个JAR文件,直到找到所要的类或者资源。
如果类装载器试图寻找一个不存在的资源,那么在应用程序或者applet中的所有JAR文件都会下载。
对于大型的网络应用程序和applet,这会导致启动缓慢、响应迟缓并浪费带宽。
从JDK1.3以后,JAR文件格式开始支持索引以优化网络应用程序中类的搜索过程,特别是applet。
JarIndex机制收集在applet或者应用程序中定义的所有JAR文件的内容,并将这些信息存储到第一个JAR文件中的索引文件中。
下载了第一个JAR文件后,applet类装载器将使用收集的内容信息高效地装载JAR文件。
这个目录信息存储在根JAR文件的META-INF目录中的一个名为INDEX.LIST的简单文本文件中。
创建一个JarIndex
可以通过在jar命令中指定-i选项创建一个JarIndex。
假设我们的目录结构如下图所示:
图2.JarIndex
您将使用下述命令为JarIndex_Main.jar、JarIndex_test.jar和JarIndex_test1.jar创建一个索引文件:
jar-iJarIndex_Main.jarJarIndex_test.jarSampleDir/JarIndex_test1.jar
INDEX.LIST文件的格式很简单,包含每个已索引的JAR文件中包含的包或者类的名字,如清单2所示:
清单2.JarIndexINDEX.LIST文件示例
JarIndex-Version:
1.0
JarIndex_Main.jar
sp
JarIndex_test.jar
Sample
SampleDir/JarIndex_test1.jar
org
org/apache
org/apache/xerces
org/apache/xerces/framework
org/apache/xerces/framework/xml4j
回页首
结束语
JAR格式远远超出了一种压缩格式,它有许多可以改进效率、安全性和组织Java应用程序的功能。
因为这些功能已经建立在核心平台--包括编译器和类装载器--中了,所以开发人员可以利用JAR文件格式的能力简化和改进开发和部署过程。
.
参考资料
您可以参阅本文在developerWorks全球站点上的英文原文.
参阅jar实用程序的命令行选项的文档。
RaffiKrikorian在ONJava上发表的文章提供了有关programmaticallysigningaJARfile的帮助。
这篇关于JavaArchiveTool的文档解释了创建和操作JAR文件可以使用的选项。
文章“JavaWebStart”(developerWorks,2001年9月)描述了如何使用这种技术,以便允许应用程序可以指定所需的JAR文件并动态下载它们。
有关J2EE服务器(比如IBMWebSphereApplicationServer)使用JAR文件格式的不同方式,请参阅“WhatareJavaArchive(JAR)files?
”
JAR格式是WAR(WebArchive)格式的基础,WAR用于在J2EE容器中部署Servlet和JSP应用程序。
更多内容请参阅“WhatareWARfiles?
”。
JAR格式也是EAR(EnterpriseArchive)格式的基础,EAR用于在J2EE容器中部署EJB。
更多内容请参阅“WhatareEnterpriseArchive(EAR)files?
”。
在developerWorksJava技术专区上可以找到数百篇关于Java编程的各个方面的文章。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JAR 文件揭密 文件 揭密