JAR包結構,META-INF/MANIFEST.MF文件詳細說明[全部屬性][打包][JDK]
轉載請註:[https://www.cnblogs.com/applerosa/p/9736729.html]
常見的屬性
jar文件的用途
壓縮的和未壓縮的
jar工具
可執行的JAR
1.創建可執行JAR
2.啟動可執行JAR
3.擴展打包
4.JAR文件中的安全性..
5.數字簽名.
6.jarsigner工具.
7.JAR索引
JAR(Java Archive File),Java 檔案文件.通常jar 為壓縮文件, 與 ZIP/RAR 壓縮文件 一樣的概念, 區別在於 jar 文件中存在一個名為META-INF/MANIFEST.MF 的清單文件, 關於JAR包的描述信息、啟動時的配置信息和安全性信息等均保存在其中,可以理解為 jar 的一個‘配置文件‘.
以spring-boot-starter-2.0.5.RELEASE.jar為例,用工具打開:
一般都會存在一些屬性,某些屬性只是為了說明jar的信息,還有一些屬性,時為能夠讓jar正常的執行裏面類的功能,比如Mysql 的: mysql-connector-java-8.0.11.jar 裏面就一堆屬性.
關於jar的官方說明文檔: https://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html
一、 常見的屬性:
基礎屬性:
1) Manifest-Version: 用來定義 manifest文件 的版本,例如:Manifest-Version: 1.0
2) Created-By: 該文件的生成者,一般該屬性是由jar命令行工具生成的,例如:Created-By: Apache Ant 1.8 .2
3) Signature-Version: 簽名版本
4) Class-Path: 依賴項列表,若存在多個依賴項時則采用空格分隔。依賴項路徑為以JAR包路徑為參考系的相對路徑, 有個小細節就是, 如果自己生成這個文件,在引用了所有的以來後, 後面還有一個 ‘.‘, 對,一個點;
1.可執行屬性:
Main-Class: main函數所在的全限定類名,該類必須是一個可執行的類,可以俠義理解為存在 main()函數的類
一旦定義了此屬性,即可通過 java -jar example.jar 來運行此jar包
其他屬性:
2.小程序(Applet)相關屬性
1. Extendsion-List 該屬性指定了小程序需要的擴展信息列表,列表中的每個名字對應以下的屬性
2. <extension>-Extension-Name
3. <extension>-Specification-Version
4. <extension>-Implementation-Version
5. <extension>-Implementation-Vendor-Id
6. <extension>-Implementation-URL
3.擴展標識屬性
Extension-Name 該屬性定義了jar文件的標識,例如Extension-Name: Struts Framework
4.包擴展屬性
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 (這點我還不是很理解)
5.簽名相關屬性
簽名方面的屬性我們可以來參照JavaMail所提供的mail.jar中的一段
- Name: javax/mail/Address.class
- Digest-Algorithms: SHA MD5
- SHA-Digest: AjR7RqnN//cdYGouxbd06mSVfI4=
- MD5-Digest: ZnTIQ2aQAtSNIOWXI1pQpw==
這段內容定義類簽名的類名、計算摘要的算法名以及對應的摘要內容(使用BASE方法進行編碼)
6.自定義屬性
除了前面提到的一些屬性外,你也可以在MANIFEST.MF中增加自己的屬性以及響應的值,例如J2ME程序jar包中就可能包含著如下信息
- MicroEdition-Configuration: CLDC-1.0
- MIDlet-Name: J2ME_MOBBER Midlet Suite
- MIDlet-Info-URL: http://www.javayou.com
- MIDlet-Icon: /icon.png
- MIDlet-Vendor: Midlet Suite Vendor
- MIDlet-1: mobber,/icon.png,mobber
- MIDlet-Version: 1.0.0
- MicroEdition-Profile: MIDP-1.0
- MIDlet-Description: Communicator
關於 jar 中信息的使用:
JDK給我們提供了用於處理這些信息的API,詳細的信息請見java.util.jar包中,我們可以通 過給JarFile傳遞一個jar文件的路徑,然後調用JarFile的getManifest方法來獲取Manifest信息。
三、 jar 文件的用途:
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 文件更快地裝載,因為在裝載過程中要解壓縮文件,但是未壓縮的文件在網絡上的下載時間可能更長。
五、jar 工具
為了用 JAR 文件執行基本的任務,要使用作為java Development Kit 的一部分提供的 Java Archive Tool ( jar 工具)。用 jar 命令調用 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
一個可執行的 jar 文件是一個自包含的 Java 應用程序,它存儲在特別配置的JAR 文件中,可以由 JVM 直接執行它而無需事先提取文件或者設置類路徑。
要運行存儲在非可執行的 JAR 中的應用程序,必須將它加入到你的類路徑中,並用名字調用應用程序的主類。就是我們常說的”第三方類庫的概念”;
但是使用可執行的 JAR 文件,我們可以不用提取它或者知道主要入口點就可以運行一個應用程序。可執行 JAR 有助於方便發布和執行 Java 應用程序。
- 創建可執行 JAR
假設應用程序中的主類是: cn.china.demo.Application.java, 裏面有個可執行的main() 函數入口,要創建一個包含應用程序代碼的 JAR 文件並標識出主類。
為此,在某個位置(不是在應用程序目錄中)創建一個名為 manifest 的文件,並在其中加入以下一行:
Main-Class: cn.china.demo.Application
然後,像這樣創建 JAR 文件:
jar cmf manifest example.jar application-dir
所要做的就是這些了 -- 現在可以用 java -jar 執行這個 JAR 文件 example.jar.
一個可執行的 JAR 必須通過 menifest 文件的頭引用它所需要的所有其他從屬 JAR。
如果使用了 -jar 選項,那麽環境變量 CLASSPATH 和在命令行中指定的所有類路徑都被 JVM 所忽略。
2. 啟動可執行 JAR
既然我們已經將自己的應用程序打包到了一個名為 example.jar 的可執行 JAR 中了,那麽我們就可以用下面的命令直接從文件啟動這個應用程序:
java -jar example.jar
3.擴展打包
擴展為 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 文件處在同一目錄中。
4.JAR 文件中的安全性
JAR 文件可以用 jarsigner 工具或者直接通過 java.security API 簽名。一個簽名的 JAR 文件與原來的 JAR 文件完全相同,只是更新了它的 manifest,並在 META-INF 目錄中增加了兩個文件,一個簽名文件和一個簽名塊文件。
JAR 文件是用一個存儲在 Keystore 數據庫中的證書簽名的。存儲在 keystore 中的證書有密碼保護,必須向jarsigner 工具提供這個密碼才能對 JAR 文件簽名。
JAR 的每一位簽名者都由在 JAR 文件的 META-INF 目錄中的一個具有 .SF 擴展名的簽名文件表示。這個文件的格式類似於 manifest 文件 -- 一組 RFC-822 頭。如下所示,它的組成包括一個主要部分,它包括了由簽名者提供的信息、但是不特別針對任何特定的 JAR 文件項,還有一系列的單獨的項,這些項也必須包含在 menifest 文件中。在驗證一個簽名的 JAR 時,將簽名文件的摘要值與對 JAR 文件中的相應項計算的摘要值進行比較。
簽名 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=
5.數字簽名
一個數字簽名是.SF 簽名文件的已簽名版本。數字簽名文件是二進制文件,並且與 .SF 文件有相同的文件名,但是擴展名不同。根據數字簽名的類型 -- RSA、DSA 或者 PGP -- 以及用於簽名 JAR 的證書類型而有不同的擴展名。
要簽名一個 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 會自動創建它。
6.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.jar 和 java.security API 以編程方式簽名 JAR(有關細節參閱 參考資料)。也可以使用像Netscape Object Signing Tool 這樣的工具。
7.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。假設我們的目錄結構如下所示:
您將使用下述命令為 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包結構,META-INF/MANIFEST.MF文件詳細說明[全部屬性][打包][JDK]