1. 程式人生 > >JAR 檔案格式的強大功能(java中jar工具的使用)

JAR 檔案格式的強大功能(java中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 的標準部分。
壓縮的和未壓縮的 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.security 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/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.jar 和 java.security 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 目錄中的一個名為 INDEX.LIST 的簡單文字檔案中。

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

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

相關推薦

JAR 檔案格式強大功能(javajar工具的使用)

大多數 Java 程式設計師都熟悉對 JAR 檔案的基本操作。但是隻有少數程式設計師瞭解 JAR 檔案格式的強大功能。在本文中,作者探討了 JAR 格式的許多功能和優勢,包括打包、可執行的 JAR 檔案、安全性和索引。JAR 檔案是什麼?JAR 檔案格式以流行的 ZIP 檔案格式為基礎,用於將許多個檔案聚集為

JAVAjar包和war包的區別是

服務器 直接 jar文件 tomcat服務 一起 是把 目的 相關 web 其實jar包和war包都可以看成壓縮文件,用解壓軟件都可以打開,jar包和war包所存在的原因是,為了項目的部署和發布,通常把項目打包,通常在打包部署的時候,會在裏面加上部署的相關信息。 這個打包實

Javajar命令詳解

 做專案的時候我們肯定接觸過很多jar包,那麼jar包是什麼呢?筆者瞭解到jar是java archive file 的簡寫。從名字就可以知道,它的應用與Java息息相關。下面就詳細介紹如何自己生成jar包,這樣我們管理我們自己的程式碼(尤其是一些比較重要而且不會或者很少有修改的程式碼)。  安裝好J

javajar包的生成與使用

什麼是jar包? JAR檔案的全稱是Java Archive File,意思是Java檔案檔案。是一種壓縮檔案,與常見的ZIP壓縮檔案相容。兩者最大的區別是在JAR檔案中預設包含一個名為META-INF/MANIFEST.MF的清單檔案,這個檔案是生成JAR檔案時由系統自動建立的。 使用

關於檔案的INode與Java檔案操作介面

本文由作者周樑偉授權網易雲社群釋出。 近日做的專案中涉及到多程序共同讀寫多個檔案的問題,檔名和最後修改時間都是可能會被頻繁修改的,因而識別檔案的唯一性會產生相當的麻煩,於是專門再學習了一下檔案系統對檔案的組織管理方式。 一、    檔案在檔案系統中的組織方式 一塊物

[原始碼和文件分享]根據PE檔案格式從匯入表獲取載入的DLL並遍歷匯入函式名稱和地址

背景 瞭解 PE 檔案格式,對於做一些資料分析都是比較重要的基礎。在 PE 檔案格式中,理解匯入表以及匯出表的工作原理,又是重中之重。理解了 PE 格式的匯入表,就可以修改 PE 格式進行 DLL 注入,也可以修改匯入表實現 API HOOK 等。理解了 PE 格式的匯出表,可以不需要 WIN3

[原始碼和文件分享]根據PE檔案格式從匯出表獲取指定匯出函式的地址

背景 瞭解 PE 檔案格式,對於做一些資料分析都是比較重要的基礎。在 PE 檔案格式中,理解匯入表以及匯出表的工作原理,又是重中之重。理解了 PE 格式的匯入表,就可以修改 PE 格式進行 DLL 注入,也可以修改匯入表實現 API HOOK 等。理解了 PE 格式的匯出表,可以不需要 WIN3

layout下新建了XML檔案,但R.java沒有生成id(已解決)

 描述:方案1.xml出錯了,導致程式不能自動編譯,將大寫改成小寫的,xml命名不能有大寫字母的。 2. 右鍵--》Android tools --> fix project properties 3.是不是你的程式碼有語法錯誤,導致不能生成r.java clean一下 4.那就重新指定下sdk版本。

將Windows檔案路徑轉換為java可識別的檔案路徑

在Windows中的檔案路徑格式為 D:\source\l.c 而在java中的檔案路徑格式為 D:/source/l.c 在java中使用前者則會報錯,所以需要先將Windows中的檔案路徑轉換為java中可識別的路徑。 作如下處理: String s

java工具

1.判斷一個字串是否為空 org.apache.commons.lang3.StringUtils.isNotBlank(string) 2.將陣列轉為list String[] companyIdSplit = companyId.split(","); List c

java高併發系列 - 第22天:java底層工具類Unsafe,高手必須要了解

這是java高併發系列第22篇文章,文章基於jdk1.8環境。 本文主要內容 基本介紹 通過反射獲取Unsafe例項 Unsafe中的CAS操作 Unsafe中原子操作相關方法介紹 Unsafe中執行緒排程相關方法 park和unpark示例 Unsafe鎖示例 Unsafe中保證變數的可見性 Unsafe

java 讀取jar檔案

參考: https://blog.csdn.net/rchm8519/article/details/39557499 參考: https://www.cnblogs.com/zeciiii/p/4178824.html  需求: 我自己寫了一個Java 的記事本工具,然後實現

javajar檔案

官方英文介紹******************************************************************************************* Introduction JAR file is a file format

Java使用Jar包時讀取當前jar檔案所在的目錄工具

在實際使用中,jar包所放的位置是不一定的所以要動態獲取當前目錄 package com.gj5u.publics.util; import java.io.File; /** * 獲取打包後

Java程式打包成jar檔案(並使用bat格式的檔執行jar包)

把Java程式打包成jar檔案,並使用bat格式的檔執行jar包。 1.     首先建立一個格式為.MF的檔:如TEST.MF。 在配置檔案中需做如下配置: Manifest-Version: 1.0 (設定版本號) Class-Path: . Test01_lib/co

0066 Linux多個Java檔案打包成單個可執行jar檔案及其manifest.mf檔案編寫規則

現在我有三個Java類檔案:GuessGame.java Player.java GameLauncher.java(含主函式) 先用編譯命令: javac GuessGame.java Player

java web專案classes資料夾下的class和WEB-INF/libjar裡的class檔案載入順序

如果是釋出到weblogic的話,可以在WebContent\WEB-INF\weblogic.xml裡面配置。 參考配置如下: <?xml version="1.0" encoding="UTF-8"?> <weblogic-web-app xmlns="http://www.b

JavaEar、Jar、War檔案之間有何不同?

JAR WAR EAR 英文 Java Archive file   Web Archive file Enterprise Archive file 包含內容 class、properties檔案,是檔案封裝的最小單元; Servlet、JSP頁面、JSP標記庫、JAR庫檔案、HTML/X

javajar讀取檔案 三種方法

Sample1-利用Manifest檔案讀取jar中的檔案 1.檔案目錄 test--      --a.text      --b.gif 2. Menifest檔案內容: Manifest-Version: 1.0 abc: test/a.txt iconname: t

命令列執行Java程式載入指定目錄Jar檔案

經常遇到需要新增第三方jar檔案的情況。在命令列狀態下要載入外部的jar檔案非常麻煩,很不好搞,在網上折騰了很久終於搞定了,在這裡做個筆記: 編譯:javac -Djava.ext.dirs=./lib Test.java執行:java -Djava.ext.dirs=./