Java JAR文件的深入探索与实践
1. 查找类所在的JAR文件
在Java开发中,有时需要确定某个类位于哪个JAR文件中,或者找出包含特定类及其相关类的所有JAR文件。例如,执行相关操作时,可能会得到如下输出:
(inside c:\program files\java\jdk1.6.0\jre\lib\rt.jar)
java/security/spec/RSAPrivateKeySpec.class
(inside c:\program files\java\jdk1.6.0\jre\lib\rt.jar)
sun/security/rsa/RSAPrivateKeyImpl.class
这表明
RSAPrivateKey
或相关类位于
c:\program files\java\jdk1.6.0\jre\lib\rt.jar
文件中。若搜索更生僻的类,如
ByteToCharDBCS_EBCDIC
,搜索结果中会找到
charsets.jar
文件。利用该功能,不仅能找到类所在的JAR文件,还能找出包含该类的所有JAR文件,有助于解决类路径混乱的问题。
2. 探索认可目录
在Java运行时环境(JRE)的安装中,存在一些不属于标准Java API的包,这些包通常是常见的第三方库,被视为认可包,即作为Java API的扩展进行分发。例如,
org.omg.CORBA
包提供了CORBA功能。由于这些包可供Java程序使用,当分发已存在于认可目录中的第三方库时,可能会发生冲突。
Java提供了认可标准覆盖机制,允许在认可目录中安装库的较新版本。要覆盖认可标准,可将JAR文件放置在JRE内的
endorsed
目录中。该目录在Windows和Unix系统中都位于JRE安装目录下的
lib
目录内。若安装了多个JRE或JDK,需确保将JAR文件放置在正确的认可目录中,以便执行的虚拟机能够识别这些JAR文件。若想使用不同的目录来覆盖认可标准,可在
java.endorsed.dirs
系统属性中指定。在该属性中,可列出一个或多个包含所需JAR文件的目录,目录之间用
File.pathSeparatorChar
分隔,该分隔符因系统而异。
以下是可被覆盖的标准API包列表:
| 可覆盖的包 |
| — |
| javax.rmi.CORBA |
| org.omg.DynamicAny |
| org.omg.CORBA |
| org.omg.DynamicAny.DynAnyFactoryPackage |
| org.omg.CORBA.DynAnyPackage |
| org.omg.DynamicAny.DynAnyPackage |
| org.omg.CORBA.ORBPackage |
| org.omg.IOP |
| org.omg.CORBA.portable |
| org.omg.IOP.CodecFactoryPackage |
| org.omg.CORBA.TypeCodePackage |
| org.omg.IOP.CodecPackage |
| org.omg.CORBA_2_3 |
| org.omg.Messaging |
| org.omg.CORBA_2_3.portable |
| org.omg.PortableInterceptor |
| org.omg.CosNaming |
| org.omg.PortableInterceptor.ORBInitInfoPackage |
| org.omg.CosNaming.Naming |
| org.omg.PortableServer.ContextExtPackage |
| org.omg.PortableServer.CurrentPackage |
| org.omg.CosNaming.Naming.ContextPackage |
| org.omg.Dynamic |
3. 探索Java归档文件(JAR)
Java的成功离不开其归档文件格式的创建。Java归档文件(JAR)是一种将多个文件(包括其他JAR文件)打包成一个以
.jar
为扩展名的单个文件的方式。JAR文件使用与zip格式相同的文件压缩方式,因此可以在支持zip压缩的程序中打开和编辑JAR文件,这使得JAR文件格式在不同操作系统之间具有可移植性,因为大多数操作系统都支持zip格式或有操作zip文件的工具。
JAR文件通过压缩类、图像、音频和其他大文件,可大大减少它们的下载时间。例如,小程序及其资源可以压缩到一个JAR文件中,显著减少小程序的下载时间。
JAR文件还可以进行数字签名,以满足对应用程序有较高安全要求的架构。通过对JAR文件进行数字签名,可以确定文件的作者以及文件是否被篡改。Java 5引入了两项JAR支持的新增强功能:
- 通过在命令行JAR工具中添加新参数
-i
,实现了对JAR文件内容的更快访问,该参数允许创建JAR文件索引。
- 增加了一个用于在打开JAR文件时使用的“关闭时删除”模式的新API。
JAR文件与普通zip文件的主要区别在于其包含的清单文件,该文件位于JAR文件的
META-INF
目录中。清单文件允许调用特殊功能,如包密封和将JAR指定为可执行JAR文件。清单文件的格式类似于属性文件,接受键值对条目,用于更改JAR文件的特定设置。除了清单文件,JAR文件的
META-INF
目录中还可以创建其他文件。通过索引支持,可以在
META-INF
目录中包含一个
INDEX.LIST
文件,当调用JAR工具并指定
-i
选项时,该文件会自动生成,从而加快类加载时间。
4. 操作JAR文件
JDK包含一个名为
jar
的命令行工具,用于通过命令行创建JAR文件。在控制台窗口中输入
jar
即可执行该工具。若工具无法运行,可能是Java环境配置不正确,需重新阅读JDK的安装说明。虽然也可以从
JDK/BIN
目录运行该工具,但建议调整环境变量,以便在任何位置都能运行该工具。
执行
jar
工具的正确语法如下:
jar {ctxu}[vfm0Mi] [jar-file] [manifest-file] [-C dir] files ...
在创建第一个JAR文件之前,了解可用于创建JAR文件的选项非常重要。以下是
jar
工具的选项及其说明:
| 选项 | 描述 |
| — | — |
| c | 用于创建新的归档文件 |
| t | 列出归档文件的目录内容,是创建JAR文件后检查其内容是否成功创建且符合预期的好方法。通常将
f
选项与
t
选项结合使用,以减少输入量 |
| x | 用于从JAR文件中提取指定文件或所有文件 |
| u | 允许使用指定的新文件或更改后的文件更新JAR文件。由于更新大量文件时此任务可能很繁琐,因此更可能使用了解如何更新zip文件格式的工具或集成开发环境(IDE)来更新JAR文件 |
| v | 详细选项,在创建JAR文件时可从
jar
工具获得更多反馈,有助于调试问题 |
| f | 指定要更新的JAR文件在命令行中 |
| m | 表示向
jar
工具提供要包含在JAR文件中的清单文件 |
| 0 | 零选项,告诉
jar
工具不压缩文件,仅将它们打包到归档文件中 |
| M | 阻止创建默认的清单文件。清单文件在JAR文件中是可选的 |
| i | Java 5引入的选项,用于在JAR文件的
META-INF
目录下生成名为
INDEX.LIST
的索引信息 |
| C [DIR] | 指示
jar
工具将目录更改为指定的目录,并对引用的文件进行JAR打包 |
以下是一个创建JAR文件的示例,该JAR文件包含两个Java文件和一个
images
目录:
C:\>jar -cvf chess.jar chess
added manifest
adding: chess/(in = 0) (out= 0)(stored 0%)
adding: chess/Chess.java(in = 0) (out= 0)(stored 0%)
adding: chess/ChessGUI.java(in = 0) (out= 0)(stored 0%)
adding: chess/images/(in = 0) (out= 0)(stored 0%)
adding: chess/images/board.bmp(in = 0) (out= 0)(stored 0%)
该命令将
C:\chess
目录及其所有子目录压缩到
chess.jar
文件中。
jar
工具会在JAR文件的
META-INF
目录中自动生成一个默认的清单文件,其中仅包含一个版本字符串。
要查看JAR文件的内容,可使用
t
选项:
C:\>jar -tf chess.jar
META-INF/
META-INF/MANIFEST.MF
chess/
chess/Chess.java
chess/ChessGUI.java
chess/images/
chess/images/board.bmp
若需要解压缩JAR文件以修补或编辑其中的文件,可使用
x
选项。以下示例使用了
xvf
选项:
C:\>jar -xvf chess.jar
created: META-INF/
inflated: META-INF/MANIFEST.MF
created: chess/
extracted: chess/Chess.java
extracted: chess/ChessGUI.java
created: chess/images/
extracted: chess/images/board.bmp
该命令将JAR文件提取到当前工作目录,之后可根据需要编辑文件并重新打包。
5. 检查基本清单文件
清单文件可视为包含其所属JAR文件元数据信息的文件。通过使用清单文件,可以对JAR文件、包和扩展进行版本控制、数字签名和密封。首次创建JAR文件时,若未指定
-M
选项,将自动创建一个默认的清单文件。默认清单文件的内容可能如下所示,具体取决于所使用的Java版本:
Manifest-Version: 1.0
Created-By: 1.6.0-rc (Sun Microsystems Inc.)
清单文件分为两个主要部分:主部分和个体部分,可在个体部分列出不同文件或包的信息。不必在清单文件中列出JAR文件中的每个文件,除非计划对JAR文件中的特定文件进行签名,此时必须列出这些文件。
清单中的信息按键值对条目分隔,使用冒号(
:
)字符分隔键和值,这与属性文件类似,但属性文件使用等号(
=
)作为分隔符。Java无法理解的任何属性将被忽略,但这些属性仍可由应用程序使用,因此这些属性有时被称为特定于应用程序的属性。以下是一些常见的主要属性及其简要说明:
| 属性 | 描述 |
| — | — |
| Manifest-Version | 该属性的值是清单文件的版本 |
| Created-By | 由
jar
工具生成,是用于创建JAR的Java版本,还包括创建Java实现的供应商名称 |
| Signature-Version | 该属性的值包含JAR文件的签名版本,必须包含具有特定格式的有效版本号字符串:digit+{.digit+}* |
| Class-Path | 类加载器使用该值创建内部搜索路径,以查找应用程序所需的扩展或库。URL之间用空格分隔 |
| Main-Class | 创建自执行JAR文件时需要该属性,需指定包含
main
方法的类文件的名称。指定名称时,不要包含
.class
扩展名,否则JAR文件将无法执行 |
| Sealed | 该属性只有两个可能的值:
true
或
false
。若为
true
,则JAR文件中的所有包都将被密封,除非单独定义为不同的情况。若密封,类加载器将仅从JAR文件中加载与从JAR文件中加载的第一个类属于同一包的类 |
虽然清单文件可能不是一个令人兴奋的文件,但探索它有助于全面了解其为JAR文件提供的强大功能和灵活性。
6. 检查小程序和JAR文件
JAR文件最常见的用途之一是将小程序代码打包到JAR文件中,并通过Web浏览器像访问其他小程序一样访问它们。由于这一特性,清单中的一个特殊属性(扩展属性)可用于在小程序中包含其他包。
以下是可用于优化小程序的扩展属性列表:
| 属性 | 描述 |
| — | — |
| Extension-List | 列出希望包含在小程序中的可选包,包名之间用单个空格分隔 |
| (extension)-Extension-Name | 存储Java插件用于确定包是否已安装的包的唯一名称 |
| (extension)-Specification-Version | 告知Java插件使用该包所需的最低版本 |
| (extension)-Implementation-Version | 告知Java插件所需的包的最低实现版本。若版本过旧,插件将尝试下载该包的较新版本 |
| (extension)-Implementation-Vendor-Id | 用于为可选包分配供应商ID。Java插件将比较供应商ID,以确保获取正确的可选包 |
| (extension)-Implementation-URL | 为了让Java插件知道在哪里获取包的最新版本,必须将该属性设置为告知Java插件从何处下载最新可选包的URL |
7. 签署JAR文件
对于注重安全的应用程序,签署JAR文件非常重要,它可以确保JAR文件未被篡改且来自原始作者。JAR文件可以使用名为
jarsigner
的特殊实用工具进行签名,该工具位于
JAVA_HOME/BIN
目录中。也可以通过代码使用
java.security
API对JAR文件进行签名。
jarsigner
工具通过访问由
keytool
实用工具创建的密钥库来签署JAR文件。
keytool
用于创建公钥和私钥、发出证书请求、导入证书回复以及确定第三方的公钥是否可信。
jarsigner
工具使用私钥对JAR文件进行签名,只有知道私钥密码的人才能使用该私钥签署JAR文件。
当
jarsigner
工具对JAR文件进行签名时,
META-INF
目录中的所有条目都会被签名,甚至与签名无关的文件也会被签名。一般来说,与签名相关的文件以以下扩展名结尾:
*.RSA
、
*.SF
、
*.DSA
和
SIG-*
。
使用
java.security
API签署JAR文件比使用
jarsigner
工具要复杂得多。当JAR文件成功签署后,它必须包含更新后的清单文件、签名文件和签名块文件。在清单文件中会为每个签署的文件创建条目,示例如下:
Name: com/wrox/SampleSigned.class
SHA1-Digest: fcavHwerE23Ff4355fdsMdS=
以下是一个具体的示例,展示了如何使用
keytool
生成密钥库并创建自签名测试证书,然后使用
jarsigner
工具对之前创建的
chess.jar
文件进行签名:
7.1 生成密钥库
-
执行以下命令创建一个包含密钥的
myKeystore文件:
C:\>keytool -genkey -keystore myKeystore -alias myself
-
提示输入密钥库密码时,输入
password:
Enter keystore password: password
- 接下来,按以下内容填写个人信息:
What is your first and last name?
[Unknown]: John Doe
What is the name of your organizational unit?
[Unknown]: IT
What is the name of your organization?
[Unknown]: Wrox
What is the name of your City or Locality?
[Unknown]: Springfield
What is the name of your State or Province?
[Unknown]: Ohio
What is the two-letter country code for this unit?
[Unknown]: US
Is CN=John Doe, OU=IT, O=Wrox, L=Springfield, ST=Ohio, C=US correct?
[no]: Yes
-
最后,输入私钥密码,再次输入
password:
Enter key password for <myself>
(RETURN if same as keystore password): password
7.2 生成自签名证书
执行以下命令生成自签名证书:
C:\>keytool -selfcert -alias myself -keystore myKeystore
该命令会提示输入密钥库密码,输入之前设置的
password
。此命令可能需要一两分钟才能完成,具体取决于系统性能。
7.3 验证密钥库和证书
执行以下命令查看密钥库的内容:
C:\>keytool -list -keystore myKeystore
Enter keystore password: password
输入密码后,输出示例如下:
Keystore type: jks
Keystore provider: SUN
Your keystore contains 1 entry
myself, Jul 21, 2004, keyEntry,
Certificate fingerprint (MD5): 96:0B:2C:20:EA:DB:87:7A:64:DA:9F:68:21:85:B6:9A
若得到上述输出,则表示可以使用该密钥库和证书对JAR文件进行签名。
7.4 签署JAR文件
执行以下命令使用
jarsigner
工具签署
chess.jar
文件:
C:\>jarsigner -keystore myKeystore chess.jar myself
Enter Passphrase for keystore: password
Warning: The signer certificate will expire within six months.
7.5 验证签名
签署成功后,可通过以下两种方式验证JAR文件的签名:
- 提取JAR文件并查看其内容,应该会看到两个新文件:
Myself.dsa
和
Myself.sf
。
.dsa
(数字签名)文件不可读,但
.sf
文件可以读取,其内容示例如下:
Signature-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)
SHA1-Digest-Manifest-Main-Attributes: XpKykodQ7e3bKKW8wqLFO8VocOU=
SHA1-Digest-Manifest: eL4xJ2eU5oyO7h4VVYW0hs1pEj0=
Name: chess/images/board.bmp
SHA1-Digest: wvxwx9Dqd+jbKoe8e7raVxSfNzI=
Name: chess/ChessGUI.java
SHA1-Digest: JlWKkQ9l5/82bHxMdf4nzrmphH0=
Name: chess/Chess.java
SHA1-Digest: Y4jUlkFH64RojRERTRBEIZRC+uc=
这些新条目显示了
jarsigner
为每个签署的文件生成的签名,这些条目也会显示在
manifest.mf
文件中。
- 使用
jarsigner
工具的
-verify
选项验证JAR文件的签名:
C:\>jarsigner -verbose -verify chess.jar
若验证成功,将看到以下输出:
289 Wed July 21 21:28:58 EDT 2004 META-INF/MANIFEST.MF
410 Wed July 21 21:28:58 EDT 2004 META-INF/MYSELF.SF
1008 Wed July 21 21:28:58 EDT 2004 META-INF/MYSELF.DSA
0 Wed July 21 13:36:18 EDT 2004 META-INF/
0 Wed July 21 13:27:02 EDT 2004 chess/
sm 0 Wed July 21 13:26:32 EDT 2004 chess/Chess.java
sm 0 Wed July 21 13:26:42 EDT 2004 chess/ChessGUI.java
0 Wed July 21 13:27:14 EDT 2004 chess/images/
sm 0 Wed July 21 13:27:08 EDT 2004 chess/images/board.bmp
s = signature was verified
m = entry is listed in manifest
k = at least one certificate was found in keystore
i = at least one certificate was found in identity scope
jar verified.
若验证失败,
jarsigner
工具将抛出安全异常,或者若JAR文件根本未签名,将返回消息表明JAR文件未签名(签名缺失或无法解析)。
JAR文件还可以由多个人进行签名,每个人运行
jarsigner
工具生成的签名都会存储在
META-INF
目录中,就像一个人签名的情况一样。甚至可以使用不同版本的JDK对JAR文件进行签名,通过上述用于签署JAR文件和创建密钥库的工具,可以实现多种安全选项。
在结束之前,让我们仔细看看
jarsigner
工具可以使用的选项:
| 选项 | 描述 |
| — | — |
| keystore
| 签署JAR文件时必需,若未指定要使用的密钥库文件,将默认使用用户主目录下的
.keystore
文件。可以为
URL
参数指定密钥库文件的完整路径和文件名 |
| storepass
| 用于提供访问计划在签署JAR文件时使用的密钥库所需的密码 |
| storetype
| 用于指定要使用的密钥库类型。
security.properties
文件中有一个名为
keystore.type
的条目,若未提供
storetype
,
jarsigner
工具将默认使用该值 |
| keypass
| 若私钥密码与密钥库密码不同,则需要提供该密码。若未提供此选项,必要时将提示输入密码 |
| sigfile
| 指定用于生成
.sf
和
.dsa
文件的文件名的基础部分。此选项允许覆盖
jarsigner
工具生成的默认值 |
通过以上步骤和工具,你可以全面掌握Java JAR文件的操作和安全签名,确保在开发和部署Java应用程序时能够高效、安全地使用JAR文件。
8. 总结与最佳实践
8.1 关键要点回顾
-
JAR文件基础
:JAR文件是Java中重要的归档文件格式,它将多个文件打包成一个以
.jar为扩展名的文件,使用与zip相同的压缩方式,具有可移植性。能减少文件下载时间,还可进行数字签名以保障安全。 -
清单文件
:位于
META-INF目录的清单文件是JAR文件的重要组成部分,可用于版本控制、数字签名、包密封等,包含主部分和个体部分,通过键值对设置JAR文件属性。 -
操作工具
:
jar工具用于创建、查看、提取和更新JAR文件;keytool用于生成密钥库和证书;jarsigner用于签署JAR文件。
8.2 最佳实践建议
-
JAR文件创建
:在创建JAR文件时,合理使用
jar工具的选项。例如,使用-cvf选项创建并详细输出创建过程,使用-i选项创建索引以加快类加载。 -
清单文件配置
:根据需求配置清单文件的属性。如创建可执行JAR文件时,设置
Main-Class属性;需要引用外部库时,设置Class-Path属性。 -
安全签名
:对于需要安全保障的JAR文件,务必进行数字签名。使用
keytool生成安全的密钥库和证书,使用jarsigner进行签名,并定期验证签名的有效性。
9. 常见问题与解决方案
9.1 类路径问题
- 问题描述 :在使用JAR文件时,可能会遇到类路径混乱的问题,导致程序无法找到所需的类。
-
解决方案
:
-
检查
Class-Path属性:确保清单文件中的Class-Path属性正确列出了所需的JAR文件和目录。 -
检查环境变量:确保
CLASSPATH环境变量包含了所有必要的JAR文件和目录。 - 使用绝对路径:在引用JAR文件时,尽量使用绝对路径,避免相对路径带来的问题。
-
检查
9.2 签名验证失败
-
问题描述
:使用
jarsigner -verify验证JAR文件签名时,可能会出现验证失败的情况。 -
解决方案
:
- 检查证书有效期:确保签名使用的证书未过期,若证书即将过期,及时更新证书。
- 检查密钥库密码:确保在签署和验证JAR文件时使用的密钥库密码正确。
- 检查JAR文件完整性:确保JAR文件在传输或存储过程中未被篡改。
9.3 JAR文件无法执行
- 问题描述 :创建的可执行JAR文件无法正常执行。
-
解决方案
:
-
检查
Main-Class属性:确保清单文件中的Main-Class属性正确指定了包含main方法的类,且不包含.class扩展名。 -
检查依赖库:确保JAR文件中包含了所有必要的依赖库,或者在
Class-Path属性中正确列出了外部依赖库。
-
检查
10. 未来趋势与展望
10.1 技术发展趋势
- 性能优化 :未来JAR文件的处理性能可能会进一步提升,例如更高效的压缩算法、更快的类加载机制。
- 安全增强 :随着安全需求的不断增加,JAR文件的数字签名技术可能会更加完善,提供更高级别的安全保障。
- 与容器技术集成 :随着容器技术的广泛应用,JAR文件可能会更好地与容器化环境集成,实现更便捷的部署和管理。
10.2 对开发者的影响
- 学习成本 :开发者需要不断学习新的技术和工具,以跟上JAR文件技术的发展。
- 开发效率 :更高效的JAR文件处理技术将提高开发者的开发效率,减少部署和调试时间。
- 安全意识 :开发者需要更加重视JAR文件的安全问题,采取有效的安全措施保障应用程序的安全。
11. 总结
通过本文的介绍,我们全面了解了Java JAR文件的相关知识,包括JAR文件的创建、操作、清单文件的配置、数字签名等。掌握这些知识和技能,能够帮助我们在Java开发和部署过程中更加高效、安全地使用JAR文件。同时,我们也了解了JAR文件技术的未来发展趋势,为我们在未来的开发工作中提供了方向。希望本文能够对广大Java开发者有所帮助,让我们在Java的世界中创造出更加优秀的应用程序。
附录:JAR文件操作流程图
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A([开始]):::startend --> B(创建JAR文件):::process
B --> C{是否需要签名?}:::decision
C -->|是| D(生成密钥库和证书):::process
D --> E(签署JAR文件):::process
C -->|否| F(使用JAR文件):::process
E --> F
F --> G{是否需要更新?}:::decision
G -->|是| H(更新JAR文件):::process
H --> F
G -->|否| I(验证JAR文件签名):::process
I --> J(结束使用JAR文件):::process
J --> K([结束]):::startend
附录:JAR文件操作命令总结表
| 操作 | 命令示例 | 说明 |
|---|---|---|
| 创建JAR文件 |
jar -cvf chess.jar chess
|
创建
chess.jar
文件,包含
chess
目录及其子目录
|
| 查看JAR文件内容 |
jar -tf chess.jar
|
列出
chess.jar
文件的内容
|
| 提取JAR文件 |
jar -xvf chess.jar
|
将
chess.jar
文件提取到当前目录
|
| 生成密钥库 |
keytool -genkey -keystore myKeystore -alias myself
|
生成名为
myKeystore
的密钥库,别名
myself
|
| 生成自签名证书 |
keytool -selfcert -alias myself -keystore myKeystore
|
为
myKeystore
中的
myself
别名生成自签名证书
|
| 签署JAR文件 |
jarsigner -keystore myKeystore chess.jar myself
|
使用
myKeystore
中的证书签署
chess.jar
文件
|
| 验证JAR文件签名 |
jarsigner -verbose -verify chess.jar
|
验证
chess.jar
文件的签名
|
超级会员免费看
1480

被折叠的 条评论
为什么被折叠?



