Dict.CN 在線詞典, 英語(yǔ)學(xué)習(xí), 在線翻譯

          都市淘沙者

          荔枝FM Everyone can be host

          統(tǒng)計(jì)

          留言簿(23)

          積分與排名

          優(yōu)秀學(xué)習(xí)網(wǎng)站

          友情連接

          閱讀排行榜

          評(píng)論排行榜

          JAR 文件格式的強(qiáng)大功能

          原文:http://blog.csdn.net/chensheng913/archive/2004/12/20/223208.aspx
          大多數(shù) Java 程序員都熟悉對(duì) JAR 文件的基本操作。但是只有少數(shù)程序員了解 JAR 文件格式的強(qiáng)大功能。在本文中,作者探討了 JAR 格式的許多功能和優(yōu)勢(shì),包括打包、可執(zhí)行的 JAR 文件、安全性和索引。
          JAR 文件是什么?
          JAR 文件格式以流行的 ZIP 文件格式為基礎(chǔ),用于將許多個(gè)文件聚集為一個(gè)文件。與 ZIP 文件不同的是,JAR 文件不僅用于壓縮和發(fā)布,而且還用于部署和封裝庫(kù)、組件和插件程序,并可被像編譯器和 JVM 這樣的工具直接使用。在 JAR 中包含特殊的文件,如 manifests 和部署描述符,用來(lái)指示工具如何處理特定的 JAR。

          一個(gè) JAR 文件可以用于:

          用于發(fā)布和使用類(lèi)庫(kù)
          作為應(yīng)用程序和擴(kuò)展的構(gòu)建單元
          作為組件、applet 或者插件程序的部署單位
          用于打包與組件相關(guān)聯(lián)的輔助資源
          JAR 文件格式提供了許多優(yōu)勢(shì)和功能,其中很多是傳統(tǒng)的壓縮格式如 ZIP 或者 TAR 所沒(méi)有提供的。它們包括:

          安全性。 可以對(duì) JAR 文件內(nèi)容加上數(shù)字化簽名。這樣,能夠識(shí)別簽名的工具就可以有選擇地為您授予軟件安全特權(quán),這是其他文件做不到的,它還可以檢測(cè)代碼是否被篡改過(guò)。

          減少下載時(shí)間。 如果一個(gè) applet 捆綁到一個(gè) JAR 文件中,那么瀏覽器就可以在一個(gè) HTTP 事務(wù)中下載這個(gè) applet 的類(lèi)文件和相關(guān)的資源,而不是對(duì)每一個(gè)文件打開(kāi)一個(gè)新連接。

          壓縮。JAR 格式允許您壓縮文件以提高存儲(chǔ)效率。

          傳輸平臺(tái)擴(kuò)展。 Java 擴(kuò)展框架(Java Extensions Framework)提供了向 Java 核心平臺(tái)添加功能的方法,這些擴(kuò)展是用 JAR 文件打包的(Java 3D 和 JavaMail 就是由 Sun 開(kāi)發(fā)的擴(kuò)展例子)。

          包密封。 存儲(chǔ)在 JAR 文件中的包可以選擇進(jìn)行密封,以增強(qiáng)版本一致性和安全性。密封一個(gè)包意味著包中的所有類(lèi)都必須在同一 JAR 文件中找到。

          包版本控制。 一個(gè) JAR 文件可以包含有關(guān)它所包含的文件的數(shù)據(jù),如廠商和版本信息。

          可移植性。 處理 JAR 文件的機(jī)制是 Java 平臺(tái)核心 API 的標(biāo)準(zhǔn)部分。
          壓縮的和未壓縮的 JAR
          jar 工具(有關(guān)細(xì)節(jié)參閱 jar 工具)在默認(rèn)情況下壓縮文件。未壓縮的 JAR 文件一般可以比壓縮過(guò)的 JAR 文件更快地裝載,因?yàn)樵谘b載過(guò)程中要解壓縮文件,但是未壓縮的文件在網(wǎng)絡(luò)上的下載時(shí)間可能更長(zhǎng)。

          META-INF 目錄
          大多數(shù) JAR 文件包含一個(gè) META-INF 目錄,它用于存儲(chǔ)包和擴(kuò)展的配置數(shù)據(jù),如安全性和版本信息。Java 2 平臺(tái)識(shí)別并解釋 META-INF 目錄中的下述文件和目錄,以便配置應(yīng)用程序、擴(kuò)展和類(lèi)裝載器:

          MANIFEST.MF。 這個(gè) manifest 文件定義了與擴(kuò)展和包相關(guān)的數(shù)據(jù)。

          INDEX.LIST。 這個(gè)文件由 jar 工具的新選項(xiàng) -i 生成,它包含在應(yīng)用程序或者擴(kuò)展中定義的包的位置信息。它是 JarIndex 實(shí)現(xiàn)的一部分,并由類(lèi)裝載器用于加速類(lèi)裝載過(guò)程。

          xxx.SF。 這是 JAR 文件的簽名文件。占位符 xxx 標(biāo)識(shí)了簽名者。

          xxx.DSA。 與簽名文件相關(guān)聯(lián)的簽名程序塊文件,它存儲(chǔ)了用于簽名 JAR 文件的公共簽名。
          jar 工具
          為了用 JAR 文件執(zhí)行基本的任務(wù),要使用作為Java Development Kit 的一部分提供的 Java Archive Tool (jar 工具)。用 jar 命令調(diào)用 jar 工具。表 1 顯示了一些常見(jiàn)的應(yīng)用:

          表 1. 常見(jiàn)的 jar 工具用法 功能 命令
          用一個(gè)單獨(dú)的文件創(chuàng)建一個(gè) JAR 文件 jar cf jar-file input-file...
          用一個(gè)目錄創(chuàng)建一個(gè) JAR 文件 jar cf jar-file dir-name
          創(chuàng)建一個(gè)未壓縮的 JAR 文件 jar cf0 jar-file dir-name
          更新一個(gè) JAR 文件 jar uf jar-file input-file...
          查看一個(gè) JAR 文件的內(nèi)容 jar tf jar-file
          提取一個(gè) JAR 文件的內(nèi)容 jar xf jar-file
          從一個(gè) JAR 文件中提取特定的文件 jar xf jar-file archived-file...
          運(yùn)行一個(gè)打包為可執(zhí)行 JAR 文件的應(yīng)用程序 java -jar app.jar

          可執(zhí)行的 JAR
          一個(gè)可執(zhí)行的 jar 文件是一個(gè)自包含的 Java 應(yīng)用程序,它存儲(chǔ)在特別配置的JAR 文件中,可以由 JVM 直接執(zhí)行它而無(wú)需事先提取文件或者設(shè)置類(lèi)路徑。要運(yùn)行存儲(chǔ)在非可執(zhí)行的 JAR 中的應(yīng)用程序,必須將它加入到您的類(lèi)路徑中,并用名字調(diào)用應(yīng)用程序的主類(lèi)。但是使用可執(zhí)行的 JAR 文件,我們可以不用提取它或者知道主要入口點(diǎn)就可以運(yùn)行一個(gè)應(yīng)用程序。可執(zhí)行 JAR 有助于方便發(fā)布和執(zhí)行 Java 應(yīng)用程序。

          創(chuàng)建可執(zhí)行 JAR
          創(chuàng)建一個(gè)可執(zhí)行 JAR 很容易。首先將所有應(yīng)用程序代碼放到一個(gè)目錄中。假設(shè)應(yīng)用程序中的主類(lèi)是 com.mycompany.myapp.Sample。您要?jiǎng)?chuàng)建一個(gè)包含應(yīng)用程序代碼的 JAR 文件并標(biāo)識(shí)出主類(lèi)。為此,在某個(gè)位置(不是在應(yīng)用程序目錄中)創(chuàng)建一個(gè)名為 manifest 的文件,并在其中加入以下一行:

          Main-Class: com.mycompany.myapp.Sample


          然后,像這樣創(chuàng)建 JAR 文件:

          jar cmf manifest ExecutableJar.jar application-dir


          所要做的就是這些了 -- 現(xiàn)在可以用 java -jar 執(zhí)行這個(gè) JAR 文件 ExecutableJar.jar。

          一個(gè)可執(zhí)行的 JAR 必須通過(guò) menifest 文件的頭引用它所需要的所有其他從屬 JAR。如果使用了 -jar 選項(xiàng),那么環(huán)境變量 CLASSPATH 和在命令行中指定的所有類(lèi)路徑都被 JVM 所忽略。

          啟動(dòng)可執(zhí)行 JAR
          既然我們已經(jīng)將自己的應(yīng)用程序打包到了一個(gè)名為 ExecutableJar.jar 的可執(zhí)行 JAR 中了,那么我們就可以用下面的命令直接從文件啟動(dòng)這個(gè)應(yīng)用程序:

          java -jar ExecutableJar.jar

          包密封
          密封 JAR 文件中的一個(gè)包意味著在這個(gè)包中定義的所有類(lèi)都必須在同一個(gè) JAR 文件中找到。這使包的作者可以增強(qiáng)打包類(lèi)之間的版本一致性。密封還提供了防止代碼篡改的手段。

          要密封包,需要在 JAR 的 manifest 文件中為包添加一個(gè) Name 頭,然后加上值為“true”的 Sealed 頭。與可執(zhí)行的 JAR 一樣,可以在創(chuàng)建 JAR 時(shí),通過(guò)指定一個(gè)具有適當(dāng)頭元素的 manifest 文件密封一個(gè) JAR,如下所示:

          Name: com/samplePackage/
          Sealed: true

          Name 頭標(biāo)識(shí)出包的相對(duì)路徑名。它以一個(gè)“/”結(jié)束以與文件名區(qū)別。在 Name 頭后面第一個(gè)空行之前的所有頭都作用于在 Name 頭中指定的文件或者包。在上述例子中,因?yàn)?Sealed 頭出現(xiàn)在 Name 頭后并且中間沒(méi)有空行,所以 Sealed 頭將被解釋為只應(yīng)用到包 com/samplePackage 上。

          如果試圖從密封包所在的 JAR 文件以外的其他地方裝載密封包中的一個(gè)類(lèi),那么 JVM 將拋出一個(gè) SecurityException。

          擴(kuò)展打包
          擴(kuò)展為 Java 平臺(tái)增加了功能,在 JAR 文件格式中已經(jīng)加入了擴(kuò)展機(jī)制。擴(kuò)展機(jī)制使得 JAR 文件可以通過(guò) manifest 文件中的 Class-Path 頭指定所需要的其他 JAR 文件。

          假設(shè) extension1.jar 和 extension2.jar 是同一個(gè)目錄中的兩個(gè) JAR 文件,extension1.jar 的 manifest 文件包含以下頭:

          Class-Path: extension2.jar

          這個(gè)頭表明 extension2.jar 中的類(lèi)是 extension1.jar 中的類(lèi)的擴(kuò)展類(lèi)。extension1.jar 中的類(lèi)可以調(diào)用 extension2.jar 中的類(lèi),并且不要求 extension2.jar 處在類(lèi)路徑中。

          在裝載使用擴(kuò)展機(jī)制的 JAR 時(shí),JVM 會(huì)高效而自動(dòng)地將在Class-Path 頭中引用的 JAR 添加到類(lèi)路徑中。不過(guò),擴(kuò)展 JAR 路徑被解釋為相對(duì)路徑,所以一般來(lái)說(shuō),擴(kuò)展 JAR 必須存儲(chǔ)在引用它的 JAR 所在的同一目錄中。

          例如,假設(shè)類(lèi) ExtensionClient 引用了類(lèi) ExtensionDemo,它捆綁在一個(gè)名為 ExtensionClient.jar 的 JAR 文件中,而類(lèi) ExtensionDemo 則捆綁在 ExtensionDemo.jar 中。為了使 ExtensionDemo.jar 可以成為擴(kuò)展,必須將 ExtensionDemo.jar 列在 ExtensionClient.jar 的 manifest 的 Class-Path 頭中,如下所示:

          Manifest-Version: 1.0
          Class-Path: ExtensionDemo.jar

          在這個(gè) manifest 中 Class-Path 頭的值是沒(méi)有指定路徑的 ExtensionDemo.jar,表明 ExtensionDemo.jar 與 ExtensionClient JAR 文件處在同一目錄中。

          JAR 文件中的安全性
          JAR 文件可以用 jarsigner 工具或者直接通過(guò) java.security API 簽名。一個(gè)簽名的 JAR 文件與原來(lái)的 JAR 文件完全相同,只是更新了它的 manifest,并在 META-INF 目錄中增加了兩個(gè)文件,一個(gè)簽名文件和一個(gè)簽名塊文件。

          JAR 文件是用一個(gè)存儲(chǔ)在 Keystore 數(shù)據(jù)庫(kù)中的證書(shū)簽名的。存儲(chǔ)在 keystore 中的證書(shū)有密碼保護(hù),必須向 jarsigner 工具提供這個(gè)密碼才能對(duì) JAR 文件簽名。

          圖 1. Keystore 數(shù)據(jù)庫(kù)

          JAR 的每一位簽名者都由在 JAR 文件的 META-INF 目錄中的一個(gè)具有 .SF 擴(kuò)展名的簽名文件表示。這個(gè)文件的格式類(lèi)似于 manifest 文件 -- 一組 RFC-822 頭。如下所示,它的組成包括一個(gè)主要部分,它包括了由簽名者提供的信息、但是不特別針對(duì)任何特定的 JAR 文件項(xiàng),還有一系列的單獨(dú)的項(xiàng),這些項(xiàng)也必須包含在 menifest 文件中。在驗(yàn)證一個(gè)簽名的 JAR 時(shí),將簽名文件的摘要值與對(duì) JAR 文件中的相應(yīng)項(xiàng)計(jì)算的摘要值進(jìn)行比較。

          清單 1. 簽名 JAR 中的 Manifest 和 signature 文件
          Contents of signature file META-INF/MANIFEST.MF

          Manifest-Version: 1.0
          Created-By: 1.3.0 (Sun Microsystems Inc.)

          Name: Sample.java
          SHA1-Digest: 3+DdYW8INICtyG8ZarHlFxX0W6g=

          Name: Sample.class
          SHA1-Digest: YJ5yQHBZBJ3SsTNcHJFqUkfWEmI=

          Contents of signature file META-INF/JAMES.SF

          Signature-Version: 1.0
          SHA1-Digest-Manifest: HBstZOJBuuTJ6QMIdB90T8sjaOM=
          Created-By: 1.3.0 (Sun Microsystems Inc.)

          Name: Sample.java
          SHA1-Digest: qipMDrkurQcKwnyIlI3Jtrnia8Q=

          Name: Sample.class
          SHA1-Digest: pT2DYby8QXPcCzv2NwpLxd8p4G4=


          數(shù)字簽名
          一個(gè)數(shù)字簽名是.SF 簽名文件的已簽名版本。數(shù)字簽名文件是二進(jìn)制文件,并且與 .SF 文件有相同的文件名,但是擴(kuò)展名不同。根據(jù)數(shù)字簽名的類(lèi)型 -- RSA、DSA 或者 PGP -- 以及用于簽名 JAR 的證書(shū)類(lèi)型而有不同的擴(kuò)展名。

          Keystore
          要簽名一個(gè) JAR 文件,必須首先有一個(gè)私鑰。私鑰及其相關(guān)的公鑰證書(shū)存儲(chǔ)在名為 keystores 的、有密碼保護(hù)的數(shù)據(jù)庫(kù)中。JDK 包含創(chuàng)建和修改 keystores 的工具。keystore 中的每一個(gè)密鑰都可以用一個(gè)別名標(biāo)識(shí),它通常是擁有這個(gè)密鑰的簽名者的名字。

          所有 keystore 項(xiàng)(密鑰和信任的證書(shū)項(xiàng))都是用唯一別名訪問(wèn)的。別名是在用 keytool -genkey 命令生成密鑰對(duì)(公鑰和私鑰)并在 keystore 中添加項(xiàng)時(shí)指定的。之后的 keytool 命令必須使用同樣的別名引用這一項(xiàng)。

          例如,要用別名“james”生成一個(gè)新的公鑰/私鑰對(duì)并將公鑰包裝到自簽名的證書(shū)中,要使用下述命令:

          keytool -genkey -alias james -keypass jamespass
          -validity 80 -keystore jamesKeyStore
          -storepass jamesKeyStorePass



          這個(gè)命令序列指定了一個(gè)初始密碼“jamespass”,后續(xù)的命令在訪問(wèn) keystore “jamesKeyStore”中與別名“james”相關(guān)聯(lián)的私鑰時(shí),就需要這個(gè)密碼。如果 keystore“jamesKeyStore”不存在,則 keytool 會(huì)自動(dòng)創(chuàng)建它。

          jarsigner 工具
          jarsigner 工具使用 keystore 生成或者驗(yàn)證 JAR 文件的數(shù)字簽名。

          假設(shè)像上述例子那樣創(chuàng)建了 keystore “jamesKeyStore”,并且它包含一個(gè)別名為“james”的密鑰,可以用下面的命令簽名一個(gè) JAR 文件:

          jarsigner -keystore jamesKeyStore -storepass jamesKeyStorePass
          -keypass jamespass -signedjar SSample.jar Sample.jar james



          這個(gè)命令用密碼“jamesKeyStorePass”從名為“jamesKeyStore”的 keystore 中提出別名為“james”、密碼為“jamespass”的密鑰,并對(duì) Sample.jar 文件簽名、創(chuàng)建一個(gè)簽名的 JAR -- SSample.jar。

          jarsigner 工具還可以驗(yàn)證一個(gè)簽名的 JAR 文件,這種操作比簽名 JAR 文件要簡(jiǎn)單得多,只需執(zhí)行以下命令:

          jarsigner -verify SSample.jar



          如果簽名的 JAR 文件沒(méi)有被篡改過(guò),那么 jarsigner 工具就會(huì)告訴您 JAR 通過(guò)驗(yàn)證了。否則,它會(huì)拋出一個(gè) SecurityException, 表明哪些文件沒(méi)有通過(guò)驗(yàn)證。

          還可以用 java.util.jar 和 java.security API 以編程方式簽名 JAR(有關(guān)細(xì)節(jié)參閱參考資料)。也可以使用像 Netscape Object Signing Tool 這樣的工具。

          JAR 索引
          如果一個(gè)應(yīng)用程序或者 applet 捆綁到多個(gè) JAR 文件中,那么類(lèi)裝載器就使用一個(gè)簡(jiǎn)單的線性搜索算法搜索類(lèi)路徑中的每一個(gè)元素,這使類(lèi)裝載器可能要下載并打開(kāi)許多個(gè) JAR 文件,直到找到所要的類(lèi)或者資源。如果類(lèi)裝載器試圖尋找一個(gè)不存在的資源,那么在應(yīng)用程序或者 applet 中的所有 JAR 文件都會(huì)下載。對(duì)于大型的網(wǎng)絡(luò)應(yīng)用程序和 applet,這會(huì)導(dǎo)致啟動(dòng)緩慢、響應(yīng)遲緩并浪費(fèi)帶寬。

          從 JDK 1.3 以后,JAR 文件格式開(kāi)始支持索引以?xún)?yōu)化網(wǎng)絡(luò)應(yīng)用程序中類(lèi)的搜索過(guò)程,特別是 applet。JarIndex 機(jī)制收集在 applet 或者應(yīng)用程序中定義的所有 JAR 文件的內(nèi)容,并將這些信息存儲(chǔ)到第一個(gè) JAR 文件中的索引文件中。下載了第一個(gè) JAR 文件后,applet 類(lèi)裝載器將使用收集的內(nèi)容信息高效地裝載 JAR 文件。這個(gè)目錄信息存儲(chǔ)在根 JAR 文件的 META-INF 目錄中的一個(gè)名為 INDEX.LIST 的簡(jiǎn)單文本文件中。

          創(chuàng)建一個(gè) JarIndex
          可以通過(guò)在 jar 命令中指定 -i 選項(xiàng)創(chuàng)建一個(gè) JarIndex。假設(shè)我們的目錄結(jié)構(gòu)如下圖所示:

          圖 2. JarIndex

          您將使用下述命令為 JarIndex_Main.jar、JarIndex_test.jar 和 JarIndex_test1.jar 創(chuàng)建一個(gè)索引文件:

          jar -i JarIndex_Main.jar JarIndex_test.jar SampleDir/JarIndex_test1.jar



          INDEX.LIST 文件的格式很簡(jiǎn)單,包含每個(gè)已索引的 JAR 文件中包含的包或者類(lèi)的名字,如清單 2 所示:

          清單 2. JarIndex INDEX.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



          結(jié)束語(yǔ)
          JAR 格式遠(yuǎn)遠(yuǎn)超出了一種壓縮格式,它有許多可以改進(jìn)效率、安全性和組織 Java 應(yīng)用程序的功能。因?yàn)檫@些功能已經(jīng)建立在核心平臺(tái) -- 包括編譯器和類(lèi)裝載器 -- 中了,所以開(kāi)發(fā)人員可以利用 JAR 文件格式的能力簡(jiǎn)化和改進(jìn)開(kāi)發(fā)和部署過(guò)程。

          posted on 2006-12-16 10:46 都市淘沙者 閱讀(151) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Java Basic/Lucene/開(kāi)源資料

          主站蜘蛛池模板: 鹿泉市| 基隆市| 黄石市| 井冈山市| 堆龙德庆县| 成都市| 乌兰县| 内乡县| 钦州市| 和田市| 环江| 墨竹工卡县| 锡林浩特市| 海城市| 娱乐| 博乐市| 来宾市| 宜阳县| 昌图县| 香格里拉县| 西城区| 南澳县| 柳河县| 峨眉山市| 中江县| 农安县| 汉寿县| 肇东市| 城口县| 祁门县| 凤山县| 任丘市| 含山县| 阿克苏市| 易门县| 岚皋县| 富平县| 吉木萨尔县| 东丰县| 乡宁县| 安达市|