GalaxyPilot —— D.S


                  生命不熄,戰斗不止
          數據加載中……

          JAR 文件揭密 探索 JAR 文件格式的強大功能


          原文地址:http://www.ibm.com/developerworks/cn/java/j-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 的標準部分。

          壓縮的和未壓縮的 JAR

          jar工具 ( 有關細節參閱 jar 工具 ) 在默認情況下壓縮文件。未壓縮的 JAR 文件一般可以比壓縮過的 JAR 文件更快地裝載,因為在裝載過程中要解壓縮文件,但是未壓縮的文件在網絡上的下載時間可能更長。

          META-INF 目錄

          大多數 JAR 文件包含一個 META-INF 目錄,它用于存儲包和擴展的配置數據,如安全性和版本信息。Java 2 平臺識別并解釋 META-INF 目錄中的下述文件和目錄,以便配置應用程序、擴展和類裝載器:

          • MANIFEST.MF。這個 manifest 文件定義了與擴展和包相關的數據。
          • INDEX.LIST。這個文件由 jar工具的新選項 -i生成,它包含在應用程序或者擴展中定義的包的位置信息。它是 JarIndex 實現的一部分,并由類裝載器用于加速類裝載過程。
          • xxx.SF。 這是 JAR 文件的簽名文件。占位符 xxx標識了簽名者。
          • xxx.DSA。 與簽名文件相關聯的簽名程序塊文件,它存儲了用于簽名 JAR 文件的公共簽名。

          jar 工具

          為了用 JAR 文件執行基本的任務,要使用作為 Java Development Kit 的一部分提供的 Java Archive Tool ( jar工具 )。用 jar命令調用 jar工具。表 1 顯示了一些常見的應用:

          表 1. 常見的 jar工具用法
          功能命令
          用一個單獨的文件創建一個 JAR 文件jar cf jar-file input-file...
          用一個目錄創建一個 JAR 文件jar cf jar-file dir-name
          創建一個未壓縮的 JAR 文件jar cf0 jar-file dir-name
          更新一個 JAR 文件jar uf jar-file input-file...
          查看一個 JAR 文件的內容jar tf jar-file
          提取一個 JAR 文件的內容jar xf jar-file
          從一個 JAR 文件中提取特定的文件jar xf jar-file archived-file...
          運行一個打包為可執行 JAR 文件的應用程序java -jar app.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 文件:

           jar cmf manifest ExecutableJar.jar application-dir

          所要做的就是這些了 -- 現在可以用 java -jar執行這個 JAR 文件 ExecutableJar.jar。

          一個可執行的 JAR 必須通過 menifest 文件的頭引用它所需要的所有其他從屬 JAR。如果使用了 -jar選項,那么環境變量 CLASSPATH 和在命令行中指定的所有類路徑都被 JVM 所忽略。

          啟動可執行 JAR

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

           java -jar ExecutableJar.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 與 ExtensionClient JAR 文件處在同一目錄中。

          回頁首

          JAR 文件中的安全性

          JAR 文件可以用 jarsigner工具或者直接通過 java.securityAPI 簽名。一個簽名的 JAR 文件與原來的 JAR 文件完全相同,只是更新了它的 manifest,并在 META-INF 目錄中增加了兩個文件,一個簽名文件和一個簽名塊文件。

          JAR 文件是用一個存儲在 Keystore數據庫中的證書簽名的。存儲在 keystore 中的證書有密碼保護,必須向 jarsigner工具提供這個密碼才能對 JAR 文件簽名。

          圖 1. Keystore 數據庫
          Keystore 數據庫

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

          清單 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=

          數字簽名

          一個數字簽名是 .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 SSample.jar Sample.jar james

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

          jarsigner工具還可以驗證一個簽名的 JAR 文件,這種操作比簽名 JAR 文件要簡單得多,只需執行以下命令:

           jarsigner -verify SSample.jar

          如果簽名的 JAR 文件沒有被篡改過,那么 jarsigner工具就會告訴您 JAR 通過驗證了。否則,它會拋出一個 SecurityException, 表明哪些文件沒有通過驗證。

          還可以用 java.util.jarjava.securityAPI 以編程方式簽名 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 目錄中的一個名為 INDEX.LIST 的簡單文本文件中。

          創建一個 JarIndex
          可以通過在 jar命令中指定 -i選項創建一個 JarIndex。假設我們的目錄結構如下圖所示:

          圖 2. JarIndex
          JarIndex Demo

          您將使用下述命令為 JarIndex_Main.jar、JarIndex_test.jar 和 JarIndex_test1.jar 創建一個索引文件:

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

          INDEX.LIST 文件的格式很簡單,包含每個已索引的 JAR 文件中包含的包或者類的名字,如清單 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

          回頁首

          結束語

          JAR 格式遠遠超出了一種壓縮格式,它有許多可以改進效率、安全性和組織 Java 應用程序的功能。因為這些功能已經建立在核心平臺 -- 包括編譯器和類裝載器 -- 中了,所以開發人員可以利用 JAR 文件格式的能力簡化和改進開發和部署過程。.

          參考資料

          • 您可以參閱本文在 developerWorks 全球站點上的 英文原文.
          • 參閱 jar 實用程序的命令行選項的文檔。
          • Raffi Krikorian 在 ONJava 上發表的文章提供了有關 programmatically signing a JAR file的幫助。
          • 文章“ Java Web Start”( developerWorks,2001 年 9 月 ) 描述了如何使用這種技術,以便允許應用程序可以指定所需的 JAR 文件并動態下載它們。
          • developerWorks Java 技術專區 上可以找到數百篇關于 Java 編程的各個方面的文章。

          posted on 2014-01-02 11:32 舵手 閱讀(631) 評論(1)  編輯  收藏

          評論

          # re: JAR 文件揭密 探索 JAR 文件格式的強大功能  回復  更多評論   

          通過萬能的搜索引擎我終于找到了這里!
          大人請問你是這帖子的作者galaxyp嗎?

          起點中文網VIP文章解密程序
          http://www.52pojie.cn/forum.php?mod=viewthread&tid=171104

          如果是的話,跪求你發的那個程序啊!
          我買了不少起點的v文,可是都是些比較小眾的,沒有txt檔,不能放到kindle里隨時看好郁悶
          一直在找能轉成txt的方法,終于在這個帖子里看到了曙光
          求大人聯系Q:386118219
          非常非常感謝!!!
          2014-02-23 20:37 | 終于找到了?

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 武邑县| 安阳市| 庆元县| 都江堰市| 惠安县| 龙陵县| 宁强县| 桐梓县| 项城市| 宝应县| 孝义市| 自治县| 长宁县| 建瓯市| 安吉县| 凤翔县| 南阳市| 青河县| 涟源市| 正定县| 鱼台县| 布尔津县| 德庆县| 甘泉县| 阿拉善左旗| 前郭尔| 长子县| 荆州市| 九寨沟县| 酉阳| 沙田区| 汽车| 格尔木市| 彭泽县| 兰溪市| 神池县| 札达县| 中方县| 延寿县| 威宁| 郸城县|