MANIFEST.MF详解及配置的注意事项

MANIFEST.MF详解及配置的注意事项

2023年7月3日发(作者:)

详解及配置的注意事项⼀、详解打开Java的JAR⽂件我们经常可以看到⽂件中包含着⼀个META-INF⽬录, 这个⽬录下会有⼀些⽂件,其中必有⼀个,这个⽂件描述了该Jar⽂件的很多信息,下⾯将详细介绍⽂件的内 容,先来看中包含的⽂件内容:Manifest-Version: 1.0Created-By: Apache Ant 1.5.1Extension-Name: Struts FrameworkSpecification-Title: Struts FrameworkSpecification-Vendor: Apache Software FoundationSpecification-Version: 1.1Implementation-Title: Struts FrameworkImplementation-Vendor: Apache Software FoundationImplementation-Vendor-Id: Implementation-Version: 1.1Class-Path: commons-dig s 如果我们把MANIFEST中的配置信息进⾏分类,可以归纳出下⾯⼏个⼤类:⼀. ⼀般属性1. Manifest-Version ⽤来定义manifest⽂件的版本,例如:Manifest-Version: 1.02. Created-By 声明该⽂件的⽣成者,⼀般该属性是由jar命令⾏⼯具⽣成的,例如:Created-By: Apache Ant 1.5.13. Signature-Version 定义jar⽂件的签名版本4. Class-Path 应⽤程序或者类装载器使⽤该值来构建内部的类搜索路径⼆. 应⽤程序相关属性1. Main-Class 定义jar⽂件的⼊⼝类,该类必须是⼀个可执⾏的类,⼀旦定义了该属性即可通过 java -jar 来运⾏该jar⽂件。

三. ⼩程序(Applet)相关属性1. Extendsion-List 该属性指定了⼩程序需要的扩展信息列表,列表中的每个名字对应以下的属性2. -Extension-Name3. -Specification-Version4. -Implementation-Version5. -Implementation-Vendor-Id5. -Implementation-URL四. 扩展标识属性1. Extension-Name 该属性定义了jar⽂件的标识,例如Extension-Name: Struts Framework

五. 包扩展属性

1. Implementation-Title 定义了扩展实现的标题2. Implementation-Version 定义扩展实现的版本3. Implementation-Vendor 定义扩展实现的组织

4. Implementation-Vendor-Id 定义扩展实现的组织的标识5. Implementation-URL : 定义该扩展包的下载地址(URL)6. Specification-Title 定义扩展规范的标题7. Specification-Version 定义扩展规范的版本8. Specification-Vendor 声明了维护该规范的组织9. Sealed 定义jar⽂件是否封存,值可以是true或者false (这点我还不是很理解)六. 签名相关属性签名⽅⾯的属性我们可以来参照JavaMail所提供的中的⼀段Name: javax/mail/igest-Algorithms: SHA MD5

SHA-Digest: AjR7RqnN//cdYGouxbd06mSVfI4=MD5-Digest: ZnTIQ2aQAtSNIOWXI1pQpw==这段内容定义类签名的类名、计算摘要的算法名以及对应的摘要内容(使⽤BASE⽅法进⾏编码)七.⾃定义属性除了前⾯提到的⼀些属性外,你也可以在中增加⾃⼰的属性以及响应的值,例如J2ME程序jar包中就可能包含着如下信息MicroEdition-Configuration: CLDC-1.0MIDlet-Name: J2ME_MOBBER Midlet SuiteMIDlet-Info-URL: let-Icon: /let-Vendor: Midlet Suite VendorMIDlet-1: mobber,/,mobberMIDlet-Version: 1.0.0MicroEdition-Profile: MIDP-1.0MIDlet-Description: Communicator关 键在于我们怎么来读取这些信息呢?其实很简单,JDK给我们提供了⽤于处理这些信息的API,详细的信息请见包中,我们可以通 过给JarFile传递⼀个jar⽂件的路径,然后调⽤JarFile的getManifest⽅法来获取Manifest信息。更详细关于JAR⽂件的规范请见/j2se/1.3/docs/guide/jar/中⽂说明/developerWorks/cn/java/j-jar/附:⼤多数 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 扩展框架(Java Extensions Framework)提供了向 Java 核⼼平台添加功能的⽅法,这些扩展是⽤ JAR ⽂件打包的(Java 3D 和 JavaMail 就是由 Sun 开发的扩展例⼦)。包密封。存储在 JAR ⽂件中的包可以选择进⾏ 密封,以增强版本⼀致性和安全性。密封⼀个包意味着包中的所有类都必须在同⼀ JAR ⽂件中找到。包版本控制。⼀个 JAR ⽂件可以包含有关它所包含的⽂件的数据,如⼚商和版本信息。可移植性。处理 JAR ⽂件的机制是 Java 平台核⼼ API 的标准部分。压缩的和未压缩的 JARjar ⼯具(有关细节参阅 jar ⼯具 )在默认情况下压缩⽂件。未压缩的 JAR ⽂件⼀般可以⽐压缩过的 JAR ⽂件更快地装载,因为在装载过程中要解压缩⽂件,但是未压缩的⽂件在⽹络上的下载时间可能更长。META-INF ⽬录⼤多数 JAR ⽂件包含⼀个 META-INF ⽬录,它⽤于存储包和扩展的配置数据,如安全性和版本信息。Java 2 平台识别并解释 META-INF ⽬录中的下述⽂件和⽬录,以便配置应⽤程序、扩展和类装载器:。这个 manifest ⽂件定义了与扩展和包相关的数据。。 这个⽂件由 jar ⼯具的新选项 -i ⽣成,它包含在应⽤程序或者扩展中定义的包的位置信息。它是 JarIndex 实现的⼀部分,并由类装载器⽤于加速类装载过程。。 这是 JAR ⽂件的签名⽂件。占位符 xxx标识了签名者。。 与签名⽂件相关联的签名程序块⽂件,它存储了⽤于签名 JAR ⽂件的公共签名。jar ⼯具为了⽤ JAR ⽂件执⾏基本的任务,要使⽤作为Java Development Kit 的⼀部分提供的 Java Archive Tool ( jar ⼯具)。⽤ jar 命令调⽤ jar ⼯具。表 1 显⽰了⼀些常见的应⽤:表 1. 常见的 jar ⼯具⽤法功能命令⽤⼀个单独的⽂件创建⼀个 JAR ⽂件jar cf ⽤⼀个⽬录创建⼀个 JAR ⽂件jar cf jar-file dir-name创建⼀个未压缩的 JAR ⽂件jar cf0 jar-file dir-name更新⼀个 JAR ⽂件jar uf 查看⼀个 JAR ⽂件的内容jar tf jar-file提取⼀个 JAR ⽂件的内容jar xf jar-file从⼀个 JAR ⽂件中提取特定的⽂件jar xf 运⾏⼀个打包为可执⾏ JAR ⽂件的应⽤程序java -jar

可执⾏的 JAR⼀个 可执⾏的 jar ⽂件是⼀个⾃包含的 Java 应⽤程序,它存储在特别配置的JAR ⽂件中,可以由 JVM 直接执⾏它⽽⽆需事先提取⽂件或者设置类路径。要运⾏存储在⾮可执⾏的 JAR 中的应⽤程序,必须将它加⼊到您的类路径中,并⽤名字调⽤应⽤程序的主类。但是使⽤可执⾏的 JAR ⽂件,我们可以不⽤提取它或者知道主要⼊⼝点就可以运⾏⼀个应⽤程序。可执⾏ JAR 有助于⽅便发布和执⾏ Java 应⽤程序。创建可执⾏ JAR创建⼀个可执⾏ JAR 很容易。⾸先将所有应⽤程序代码放到⼀个⽬录中。假设应⽤程序中的主类是 。您要创建⼀个包含应⽤程序代码的 JAR ⽂件并标识出主类。为此,在某个位置(不是在应⽤程序⽬录中)创建⼀个名为 manifest 的⽂件,并在其中加⼊以下⼀⾏:Main-Class:

然后,像这样创建 JAR ⽂件:jar cmf manifest application-dir

所要做的就是这些了 -- 现在可以⽤ java -jar 执⾏这个 JAR ⽂件 。⼀个可执⾏的 JAR 必须通过 menifest ⽂件的头引⽤它所需要的所有其他从属 JAR。如果使⽤了 -jar 选项,那么环境变量 CLASSPATH 和在命令⾏中指定的所有类路径都被 JVM 所忽略。启动可执⾏ JAR既然我们已经将⾃⼰的应⽤程序打包到了⼀个名为 的可执⾏ JAR 中了,那么我们就可以⽤下⾯的命令直接从⽂件启动这个应⽤程序:java -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 ⽂件。假设 和 是同⼀个⽬录中的两个 JAR ⽂件, 的 manifest ⽂件包含以下头:Class-Path:

这个头表明 中的类是 中的类的 扩展类。 中的类可以调⽤ 中的类,并且不要求 处在类路径中。在装载使⽤扩展机制的 JAR 时,JVM 会⾼效⽽⾃动地将在 Class-Path 头中引⽤的 JAR 添加到类路径中。不过,扩展 JAR 路径被解释为相对路径,所以⼀般来说,扩展 JAR 必须存储在引⽤它的 JAR 所在的同⼀⽬录中。例如,假设类 ExtensionClient 引⽤了类 ExtensionDemo ,它捆绑在⼀个名为 的 JAR ⽂件中,⽽类 ExtensionDemo 则捆绑在 中。为了使 可以成为扩展,必须将 列在 的 manifest 的 Class-Path 头中,如下所⽰:Manifest-Version: 1.0Class-Path:

在这个 manifest 中 Class-Path 头的值是没有指定路径的 ,表明 与ExtensionClient JAR ⽂件处在同⼀⽬录中。JAR ⽂件中的安全性JAR ⽂件可以⽤ jarsigner ⼯具或者直接通过 ty API 签名。⼀个签名的 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 ⽂件Contents of signature file META-INF/fest-Version: 1.0Created-By: 1.3.0 (Sun Microsystems Inc.)Name: A1-Digest: 3+DdYW8INICtyG8ZarHlFxX0W6g=Name: HA1-Digest: YJ5yQHBZBJ3SsTNcHJFqUkfWEmI=Contents of signature file META-INF/ature-Version: 1.0SHA1-Digest-Manifest: HBstZOJBuuTJ6QMIdB90T8sjaOM=Created-By: 1.3.0 (Sun Microsystems Inc.)Name: A1-Digest: qipMDrkurQcKwnyIlI3Jtrnia8Q=Name: HA1-Digest: pT2DYby8QXPcCzv2NwpLxd8p4G4=

数字签名⼀个数字签名是.SF 签名⽂件的已签名版本。数字签名⽂件是⼆进制⽂件,并且与 .SF ⽂件有相同的⽂件名,但是扩展名不同。根据数字签名的类型 -- RSA、DSA 或者 PGP -- 以及⽤于签名 JAR 的证书类型⽽有不同的扩展名。Keystore要签名⼀个 JAR ⽂件,必须⾸先有⼀个私钥。私钥及其相关的公钥证书存储在名为 keystores 的、有密码保护的数据库中。JDK 包含创建和修改 keystores 的⼯具。keystore 中的每⼀个密钥都可以⽤⼀个别名标识,它通常是拥有这个密钥的签名者的名字。所有 keystore 项(密钥和信任的证书项)都是⽤唯⼀别名访问的。别名是在⽤ keytool -genkey 命令⽣成密钥对(公钥和私钥)并在 keystore 中添加项时指定的。之后的 keytool 命令必须使⽤同样的别名引⽤这⼀项。例如,要⽤别名“james”⽣成⼀个新的公钥/私钥对并将公钥包装到⾃签名的证书中,要使⽤下述命令:keytool -genkey -alias james -keypass jamespass -validity 80 -keystore jamesKeyStore -storepass jamesKeyStorePass

这个命令序列指定了⼀个初始密码“jamespass”,后续的命令在访问 keystore “jamesKeyStore”中与别名“james”相关联的私钥时,就需要这个密码。如果 keystore“jamesKeyStore”不存在,则 keytool 会⾃动创建它。jarsigner ⼯具jarsigner ⼯具使⽤ keystore ⽣成或者验证 JAR ⽂件的数字签名。假设像上述例⼦那样创建了 keystore “jamesKeyStore”,并且它包含⼀个别名为“james”的密钥,可以⽤下⾯的命令签名⼀个 JAR ⽂件:jarsigner -keystore jamesKeyStore -storepass jamesKeyStorePass -keypass jamespass -signedjar james

这个命令⽤密码“jamesKeyStorePass”从名为“jamesKeyStore”的 keystore 中提出别名为“james”、密码为“jamespass”的密钥,并对 ⽂件签名、创建⼀个签名的 JAR -- 。jarsigner ⼯具还可以验证⼀个签名的 JAR ⽂件,这种操作⽐签名 JAR ⽂件要简单得多,只需执⾏以下命令:jarsigner -verify 如果签名的 JAR ⽂件没有被篡改过,那么 jarsigner ⼯具就会告诉您 JAR 通过验证了。否则,它会抛出⼀个SecurityException , 表明哪些⽂件没有通过验证。还可以⽤ 和 ty API 以编程⽅式签名 JAR(有关细节参阅 参考资料)。也可以使⽤像Netscape Object Signing Tool 这样的⼯具。JAR 索引如果⼀个应⽤程序或者 applet 捆绑到多个 JAR ⽂件中,那么类装载器就使⽤⼀个简单的线性搜索算法搜索类路径中的每⼀个元素,这使类装载器可能要下载并打开许多个 JAR ⽂件,直到找到所要的类或者资源。如果类装载器试图寻找⼀个不存在的资源,那么在应⽤程序或者 applet 中的所有 JAR ⽂件都会下载。对于⼤型的⽹络应⽤程序和 applet,这会导致启动缓慢、响应迟缓并浪费带宽。从 JDK 1.3 以后,JAR ⽂件格式开始⽀持索引以优化⽹络应⽤程序中类的搜索过程,特别是 applet。JarIndex 机制收集在 applet 或者应⽤程序中定义的所有 JAR ⽂件的内容,并将这些信息存储到第⼀个 JAR ⽂件中的索引⽂件中。下载了第⼀个 JAR ⽂件后,applet 类装载器将使⽤收集的内容信息⾼效地装载 JAR ⽂件。这个⽬录信息存储在根 JAR ⽂件的 META-INF ⽬录中的⼀个名为 的简单⽂本⽂件中。创建⼀个 JarIndex

可以通过在 jar 命令中指定 -i 选项创建⼀个 JarIndex。假设我们的⽬录结构如下图所⽰:图 2. JarIndex

您将使⽤下述命令为 JarIndex_、JarIndex_ 和 JarIndex_ 创建⼀个索引⽂件:jar -i JarIndex_ JarIndex_ SampleDir/JarIndex_

⽂件的格式很简单,包含每个已索引的 JAR ⽂件中包含的包或者类的名字,如清单 2 所⽰:清单 2. JarIndex ⽂件⽰例JarIndex-Version: 1.0JarIndex_arIndex_pleSampleDir/JarIndex_org/apacheorg/apache/xercesorg/apache/xerces/frameworkorg/apache/xerces/framework/xml4j

结束语JAR 格式远远超出了⼀种压缩格式,它有许多可以改进效率、安全性和组织 Java 应⽤程序的功能。因为这些功能已经建⽴在核⼼平台 -- 包括编译器和类装载器 -- 中了,所以开发⼈员可以利⽤ JAR ⽂件格式的能⼒简化和改进开发和部署过程

⼆、配置的注意事项1. Manifest-Version、Main-Class和Class-Path后⾯跟着⼀个英⽂的冒号,冒号后⾯必须跟着⼀个空格,然后才是版本号、类和ClassPath。2. Class-Path中的各项应使⽤空格分隔,不是逗号或分号。3. Class-Path中如果有很多项,写成⼀⾏打包的时候会报错line too long,这时需要把Class-Path分多⾏写。注意:从第⼆⾏开始,必须以两个空格开头,三个以上我没试过,不过不⽤空格开头和⼀个空格开头都是不⾏的,我已经试过了。4. Class-Path写完之后最后⼀定要有⼀个空⾏。5. jar包内有些配置⽂件想放在jar包外⾯,⽐如⽂件ties:如果这个⽂件是以路径⽅式载⼊的,⽐如newfile("./config/ties"),那么将ties放在jar包相同⽬录下的 config⽬录下即可,也就是说“./”路径等价于jar包所在⽬录;如果这个⽂件是以ClassPath下的⽂件这种⽅式载⼊的,⽐如在Spring 中载⼊classpath:ties,则在MF⽂件的配置⽂件的ClassPath中添加“./”,然后将这个配置⽂件与 jar包放在同⼀个⽬录即可,当然也可以在MF⽂件的配置⽂件的ClassPath中添加“./config/”,然后把配置⽂件都放在jar包相同⽬录下的config⽬录下。如果还有问题,那就使⽤终极⼤绝招:copy!下⾯是的,copy如下 。开始:Manifest-Version: 1.0Ant-Version: Apache Ant 1.6.1Created-By: 1.3.1_04-b02 (Sun Microsystems Inc.)Extension-Name: Struts FrameworkSpecification-Title: Struts FrameworkSpecification-Vendor: The Apache Software FoundationSpecification-Version: 1.2.9Implementation-Title: Struts FrameworkImplementation-Vendor: The Apache Software FoundationImplementation-Vendor-Id: Implementation-Version: 1.2.9Class-Path: commons-fileup

结束。(包括每个空格和空⾏)

发布者:admin,转转请注明出处:http://www.yc00.com/web/1688383630a129858.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信