Java之jar打包

1、jar簡介

Java歸檔文件格式(Java Archive, JAR)能夠?qū)⒍鄠€源碼溉旋、資源等文件打包到一個歸檔文件中畸冲。這樣,有如下好處:

  • 安全性
    可以對整個jar包的內(nèi)容進行簽名观腊。
  • 減少了下載時間
    如果applet被打包成一個jar文件邑闲,那么所有相關(guān)的資源就可以在一個HTTP transaction中下載完成,而無需為每一個文件新建一個連接梧油。
  • 壓縮
    減少了磁盤空間的占用苫耸。
  • 容易擴展
    通過jar這種格式,可以和容易地將自己的程序打包提供給別人使用儡陨。
  • 包密封(Package Sealing)
    存儲在jar文件中的包可以被密封褪子,來保證版本的一致性量淌。密封可以保證一個包中的所有類都來自同一個jar文件。
  • 包版本說明
    一個jar包可以存儲關(guān)于其內(nèi)容的信息嫌褪,包括提供商呀枢、版本等。
  • 可移植性
    處理jar文件的機制是Java平臺核心API的標(biāo)準(zhǔn)模塊笼痛。

From docs.oracle.com

2裙秋、jar的使用

JDK自帶的打包工具通過jar命令來調(diào)用,jar是通過zip格式進行打包的缨伊。所以摘刑,這個jar工具也可以作為日常的壓縮、解壓縮工具來進行使用刻坊。

2.1 jar命令說明

如果安裝了JDK并配置了環(huán)境變量枷恕,在命令行中輸入jar命令,不加任何參數(shù)紧唱,就可以看到j(luò)ar命令的使用說明活尊,最下面還包含了兩個例子:

jar
用法: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...
選項:
    -c  創(chuàng)建新檔案
    -t  列出檔案目錄
    -x  從檔案中提取指定的 (或所有) 文件
    -u  更新現(xiàn)有檔案
    -v  在標(biāo)準(zhǔn)輸出中生成詳細(xì)輸出
    -f  指定檔案文件名
    -m  包含指定清單文件中的清單信息
    -n  創(chuàng)建新檔案后執(zhí)行 Pack200 規(guī)范化
    -e  為捆綁到可執(zhí)行 jar 文件的獨立應(yīng)用程序指定應(yīng)用程序入口點
    -0  僅存儲; 不使用任何 ZIP 壓縮
    -P  保留文件名中的前導(dǎo) '/' (絕對路徑) 和 ".." (父目錄) 組件
    -M  不創(chuàng)建條目的清單文件
    -i  為指定的 jar 文件生成索引信息
    -C  更改為指定的目錄并包含其中的文件(可以理解為首先cd到指定目錄)
如果任何文件為目錄, 則對其進行遞歸處理。
清單文件名, 檔案文件名和入口點名稱的指定順序與 'm', 'f' 和 'e' 標(biāo)記的指定順序相同漏益。

示例 1: 將兩個類文件歸檔到一個名為 classes.jar 的檔案中:
       jar cvf classes.jar Foo.class Bar.class
示例 2: 使用現(xiàn)有的清單文件 'mymanifest' 并將 foo/ 目錄中的所有文件歸檔到 'classes.jar' 中:
       jar cvfm classes.jar mymanifest -C foo/ .

摘自<jar命令的幫助文檔>

2.2 jar使用舉例

jar命令打包時默認(rèn)會在jar包中添加清單(manifest)文件蛹锰,如果不想添加,手動指定-M選項:

>jar -cvf HelloWorld.jar HelloWorld.class   #將HelloWorld.class文件打入jar包
    已添加清單
    正在添加: HelloWorld.class(輸入 = 427) (輸出 = 289)(壓縮了 32%)
>jar -tf HelloWorld.jar   #查看歸檔文件的內(nèi)容
    META-INF/
    META-INF/MANIFEST.MF
    HelloWorld.class
>jar -xf HelloWorld.jar META-INF/MANIFEST.MF   #解壓出其中的META-INF/MANIFEST.MF文件
>type META-INF\MANIFEST.MF   #查看清單文件的內(nèi)容
    Manifest-Version: 1.0
    Created-By: 1.8.0_51 (Oracle Corporation)
>jar -cvfM HelloWorld.jar HelloWorld.class   #將HelloWorld.class文件打入jar包绰疤,不要添加清單文件
    正在添加: HelloWorld.class(輸入 = 427) (輸出 = 289)(壓縮了 32%)
>jar -tf HelloWorld.jar
    HelloWorld.class
>jar -xf HelloWorld.jar   #解壓tar文件到當(dāng)前目錄

如果要生成可以運行的jar包铜犬,需要指定jar包的應(yīng)用程序入口點,用-e選項:

>jar -cvfe HelloWorld.jar HelloWorld HelloWorld.class   #創(chuàng)建可以運行的jar包
    已添加清單
    正在添加: HelloWorld.class(輸入 = 427) (輸出 = 289)(壓縮了 32%)
>jar -tf HelloWorld.jar   #查看歸檔的內(nèi)容
    META-INF/
    META-INF/MANIFEST.MF
    HelloWorld.class
>type META-INF\MANIFEST.MF   #查看清單文件的內(nèi)容
    Manifest-Version: 1.0
    Created-By: 1.8.0_51 (Oracle Corporation)
    Main-Class: HelloWorld
>java -jar HelloWorld.jar   #運行jar包
    Hello World!!

查看jar包的文件列表:

jar vtf  fileName.jar

3轻庆、清單文件MANIFEST.MF

jar打包時癣猾,會默認(rèn)向jar包中添加一個清單文件(MANIFEST.MF),放在META-INF目錄余爆。上面的例子中纷宇,可以看到:如果指定了jar包的入口程序,清單文件中就會多一行Main-Class: HelloWorld蛾方。實際上像捶,-e選項的作用就是向MANIFEST.MF文件中添加這樣一行信息,來聲明jar包的入口程序桩砰。當(dāng)然拓春,我們也可以直接修改清單文件的內(nèi)容。

3.1 修改清單文件的內(nèi)容

前面已經(jīng)說了亚隅,-m選項可以添加指定清單文件中的清單信息硼莽,格式如下:

jar cfm jar-file manifest-addition input-file(s)

注意:

  • manifest-addition是一個已經(jīng)存在的文本文件,其中包含著想要往jar包的清單文件中添加的清單信息煮纵。
  • manifest-addition的文件編碼格式必須是UTF-8懂鸵。
  • 清單信息每行后面必須有回車或者換行偏螺。(The text file from which you are creating the manifest must end with a new line or carriage return. The last line will not be parsed properly if it does not end with a new line or carriage return.)
  • 清單文件名, 檔案文件名和入口點名稱的指定順序與 'm', 'f' 和 'e' 標(biāo)記的指定順序相同。(前面已經(jīng)提到了)

3.2 在清單文件中聲明入口程序

>type manifest.txt   #查看清單信息的內(nèi)容
    Main-Class: HelloWorld
    
>jar -cvfm HelloWorld.jar manifest.txt HelloWorld.class   #添加清單信息到j(luò)ar包
    已添加清單
    正在添加: HelloWorld.class(輸入 = 427) (輸出 = 289)(壓縮了 32%)
>jar -xvf HelloWorld.jar META-INF\MANIFEST.MF
      已解壓: META-INF/MANIFEST.MF
>type META-INF\MANIFEST.MF
    Manifest-Version: 1.0
    Created-By: 1.8.0_51 (Oracle Corporation)
    Main-Class: HelloWorld   #可以看到清單信息成功添加
>java -jar HelloWorld.jar   #這樣指定入口程序矾瑰,生成的jar包照樣可以運行砖茸。
    Hello World!!

3.3 在清單文件中指定CLASSPATH

在運行java命令的時候,如果指定了-jar選項殴穴,那么環(huán)境變量CLASSPATH和在命令行中指定的所有類路徑都被JVM所忽略凉夯。這時,如果一個jar包引用了其它的jar包采幌,解決方案有兩個:

  1. java -cp lib\log4j-1.2.14.jar;hello.jar com.dhn.Hello (com.dhn.Hello為主類)
    在windows下多個jar之間以分號(;)隔開,最后還需要指定運行jar文件中的完整的主類名劲够。

  2. java -jar hello.jar
    這種,需要修改hello.jar中的MANIFEST.MF休傍,通過MANIFEST.MF中的Class-Path 來指定運行時需要用到的其他jar征绎,其他jar可以是當(dāng)前路徑也可以是當(dāng)前路徑下的子目錄。多個jar文件之間以空格隔開磨取。
    以下面的MANIFEST.MF文件為例

     Manifest-Version: 1.0
     Main-Class: com.ibm.portalnews.entrance.Main
     Class-Path: lib\commons-collections-3.2.jar lib\commons-configuration-1.5.jar lib\commons-lang-2.3.jar lib\commons-logging.jar lib\dom4j-1.6.1.jar lib\jaxen-1.1-beta-7.jar lib\jdom.jar lib\log4j-1.2.14.jar
    

    其中:

    • Manifest-Version表示版本號人柿,一般由IDE工具(如eclipse)自動生成
    • Main-Class 是jar文件的主類,程序的入口
      
    • Class-Path 指定需要的jar忙厌,多個jar必須要在一行上凫岖,多個jar之間以空格隔開,如果引用的jar在當(dāng)前目錄的子目錄下逢净,windows下使用\來分割哥放,linux下用/分割
      
    • 文件的冒號后面必須要空一個空格,否則會出錯
      
    • 文件的最后一行必須是一個回車換行符爹土,否則也會出錯
      

    From: java -jar classpath心得

3.4 將jar包A引用的其它jar包一同打包到A里面

這個問題甥雕,是我一直想的。如果這樣胀茵,那么將一個程序到處拷貝的話就方便的多了社露。然而,這是行不通的琼娘,因為JDK的類加載器不會加載jar包內(nèi)包含的其它jar包中的類呵哨。

當(dāng)然,這樣想過的人不止我一個轨奄,可以通過一些第三方的工具來完成。比如有個工具叫one-jar拒炎,感興趣的可以看下挪拟。

3.5 通過清單文件密封包

JAR中的Package Sealing功能是在Java 1.2引入的。在生成Jar文件時我們可以指定是否將整個Jar或者其中某幾個Package進行密封击你,如果是將Jar文件整個進行密封玉组,那就意味著其內(nèi)所有的Package都被密封了谎柄。Package一旦密封,那么Java 虛擬機一旦成功裝載密封Package中的某個類后惯雳,其后所有裝載的帶有相同Package名的類必須來自同一個Jar文件朝巫,否則將觸發(fā)Sealing Violation安全異常。

From Java中Package Sealing的探秘之旅

對包的密封方式主要有兩種:一種是對jar文件中的某些包進行密封石景,另一種是密封jar中的所有包够掠。

  • 對某些包密封腮郊。

      Manifest-Version: 1.0
      Created-By: 1.8.0_51 (Oracle Corporation)
    
      Name: com/test/hello/  
      Sealed: true
      Name: com/test/world/  
      Sealed: true  
    
  • 密封jar中的所有包。

      Manifest-Version: 1.0
      Created-By: 1.8.0_51 (Oracle Corporation)
      Sealed: true
    

概括來說,有兩種情況觸發(fā)關(guān)于Sealing的安全異常:

  1. 檢查當(dāng)前試圖加載的類對應(yīng)的Package是否已經(jīng)被JVM裝載且密封遵绰。如果已經(jīng)被裝載且密封了,但被密封的Package與當(dāng)前加載的類對應(yīng)的Package不是來自同一個Jar文件花枫,將觸發(fā)安全異常黍瞧。
  2. 檢查當(dāng)前試圖加載的類對應(yīng)的 Package是否已經(jīng)被JVM裝載且密封。如果已經(jīng)被裝載但沒有被密封椎例,但當(dāng)前試圖加載的類對應(yīng)的Package確要試圖進行密封操作挨决,將觸發(fā)安全異常。JVM不允許對已經(jīng)裝載但未密封的Package再進行密封操作订歪。

Package Sealing的好處:
Package Sealing所能帶來的好處主要是版本一致性. 我們知道Java 在運行時是嚴(yán)格按照classpath中定義的順序進行裝載和檢查脖祈,尤其是現(xiàn)在Java開源包滿天飛, 很有可能你的Java應(yīng)用程序或者中間件的classpath中會在不同的Jar文件中包含同一個Package的不同版本。這會使得程序運行產(chǎn)生不一致性結(jié)果陌粹,很難發(fā)現(xiàn)撒犀。

From: Java中Package Sealing的探秘之旅

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市掏秩,隨后出現(xiàn)的幾起案子或舞,更是在濱河造成了極大的恐慌,老刑警劉巖蒙幻,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件映凳,死亡現(xiàn)場離奇詭異,居然都是意外死亡邮破,警方通過查閱死者的電腦和手機诈豌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抒和,“玉大人矫渔,你說我怎么就攤上這事〈菝В” “怎么了庙洼?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我油够,道長蚁袭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任石咬,我火速辦了婚禮揩悄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鬼悠。我一直安慰自己删性,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布厦章。 她就那樣靜靜地躺著镇匀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪袜啃。 梳的紋絲不亂的頭發(fā)上汗侵,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天,我揣著相機與錄音群发,去河邊找鬼晰韵。 笑死,一個胖子當(dāng)著我的面吹牛熟妓,可吹牛的內(nèi)容都是我干的雪猪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼起愈,長吁一口氣:“原來是場噩夢啊……” “哼只恨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抬虽,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤官觅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后阐污,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體休涤,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年笛辟,在試婚紗的時候發(fā)現(xiàn)自己被綠了功氨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡手幢,死狀恐怖捷凄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情围来,我是刑警寧澤纵势,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布踱阿,位于F島的核電站,受9級特大地震影響钦铁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜才漆,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一牛曹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧醇滥,春花似錦黎比、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至不跟,卻和暖如春颓帝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背窝革。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工购城, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人虐译。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓瘪板,卻偏偏與公主長得像,于是被迫代替她去往敵國和親漆诽。 傳聞我的和親對象是個殘疾皇子侮攀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)厢拭,斷路器兰英,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,806評論 6 342
  • 來可以 但不能賴著不走
    你怎么想的閱讀 378評論 0 0
  • 接下來要寫的文字屬于2014年。 在微博上蚪腐,跨年的鐘聲敲響箭昵,每個人都在說新年快樂,對節(jié)日無感的我回季,也被渲染得發(fā)了一...
  • 納蘭性德的這首《長相思山一程》家制,寫盡千山萬里情。 山一程泡一,水一程颤殴,身向榆關(guān)那畔行,夜深千帳燈鼻忠。 風(fēng)一更涵但,雪一更,聒...
    小主正紅閱讀 182評論 0 0