Java打包jar內幕(初級篇)
河南大學 計算機與信息工程學院 05級 張志
這篇內容部分來自官網及維基的翻譯,大部分的代碼都親自做了測試,如果遇到問題可以聯繫我,高手們可以大略讀一下初級篇或直接略過讀高級篇。
學過c++的同學都知道,編譯過後的程序是可以直接點擊運行的,.exe文件是windows裏的可執行文件,那麼我們在java中如何產生這種可執行文件呢?解決這個問題,我們要知道java程序的打包發佈。
Java程序的打包發佈也就是打包成jar壓縮包的過程,jar壓縮包是可以直接點擊運行的,類似.exe文件,所以我們要做的就是把java源文件編譯後,打包成jar文件,那麼我們的用戶就可以直接雙擊運行了。是不是很爽。
其實,我們還可以作很多,比如我們也可以用工具把java程序做成.exe文件,我們也可以做成linux下可以運行的程序。
下面我們詳細介紹步驟,並說明每個步驟的原因,知其然也得知其所以然。
一、Java程序的打包基本上分兩部分,一部分是一般程序的打包,另一部分就是特殊的插件打包了,我們只注重一般程序的打包,插件的打包方法我們不研究,畢竟沒幾個人搞插件開發。
二、jar運行的時候,它在怎麼工作呢?
瞭解這個是很重要的,知道這個以後,你就明白爲什麼我們需要這個文件、需要哪個文件,所以要仔細看這部分。
簡單的說:
雙擊jar文件->jar會讀取manifest.mf(或者以mf爲後綴的)這個打包清單->清單裏有主類名和運行需要的庫->根據這些信息jar就可以開始運行裏面的java程序了->當有和系統進行交互的時候(比如swt需要系統的界面窗口信息,如果沒有和系統進行信息交互則不必包含系統的庫文件,其實那個時候你也沒有需要的庫文件),我們就要讀取系統的庫文件,調用系統的東西,所以我們要把系統的庫函數連接文件(***.dll)包括進來。
這些就是jar的工作內部過程,那麼下面我們就滿足它的要求,創建它。
三、立即開工
1、第一步,創建好你的swt程序,我們以這個爲例,我們不避諱任何爲題,因爲這個包含的比較全面,基本問題都遇到了,所以你要先創建一個簡單的swt程序,例如一個簡單的對話框Swttest.java。
2、下面要做第二步,寫好你的配置文件,取名爲manifest.mf(名字隨便,後綴爲mf即可)具體格式:
Manifest-Version: 1.0
Main-Class: Swttest
Class-Path: ./lib/swt.jar ./lib/runtime.jar
說明:
第一行的意思是指定清單文件的版本號,不同版本的清單文件格式是稍有不同的,所以爲了讓jar讀取正確的數據,我們必須指定它的格式,當然你也可以換取其他版本,比如2.0等,但是格式要稍微變化一下,這裏不詳細介紹了。
第二行的意思是指定主程序的類的入口,主類都明白吧,就是包含主函數的類,把這個類寫上,jar就會從這個類開始執行。
第三行的意思是由於我們要獨立運行,所以我們要把程序執行所需要的環境模擬出來,而這些包就是需要的函數和同文件等,runtime.jar時必須寫的,swt.jar不一定,如果你是一般的程序,沒有swt的事兒,那麼這個就不用。
3、第三步用jar生成結果,jar是一個生成jar包的命令,在命令行下輸入jar或jar –help 會出現:
用法:jar {ctxu}[vfm0Mi] [jar-文件] [manifest-文件] [-C 目錄] 文件名 ...
選項:
-c 創建新的存檔
-t 列出存檔內容的列表
-x 展開存檔中的命名的(或所有的〕文件
-u 更新已存在的存檔
-v 生成詳細輸出到標準輸出上
-f 指定存檔文件名
-m 包含來自標明文件的標明信息
-0 只存儲方式;未用ZIP壓縮格式
-M 不產生所有項的清單(manifest〕文件
-i 爲指定的jar文件產生索引信息
-C 改變到指定的目錄,並且包含下列文件:
如果一個文件名是一個目錄,它將被遞歸處理。
清單(manifest〕文件名和存檔文件名都需要被指定,按'm' 和 'f'標誌指定的相同順序。
示例1:將兩個class文件存檔到一個名爲 'classes.jar' 的存檔文件中:
jar cvf classes.jar Foo.class Bar.class
示例2:用一個存在的清單(manifest)文件 'mymanifest' 將 foo/ 目錄下的所有
文件存檔到一個名爲 'classes.jar' 的存檔文件中:
jar cvfm classes.jar mymanifest -C foo/ .
知道了jar命令的用法,我們開始打包我們的文件,我們不用其他工具,就用jdk自帶的jar打包我們的東西,這樣我們可以更加獨立的進行工作。
假設我現在有一個簡單的helloworld程序,主類是hello。
方法一:讓程序自動生成manifest.mf文件
jar cvf test.jar hello.class
執行語句後生成一個包,然後我們改動一下里面的文件。
加一句:Main-Class:(空格)hello
然後壓縮回jar文件,執行即可。
方法二:用我們自己寫的manifest.mf
先寫出我們自己的manifest.mf文件
jar cfm test.jar manifest.mf hello.class
注意:
如果有內部類,不用寫內部類,java會自己根據主類找出你的其他類,只要把他們的class文件全部打包進來就可以了。
如果有絕對路徑的東西,
例如javax.swing.ImageIcon icon = new javax.swing.ImageIcon("1.gif");
那麼打包後的程序將不能找到這個圖片, 因爲它引用了一個物理路徑的圖片, 它應該改成這樣:
javax.swing.ImageIcon icon = new javax.swing.ImageIcon(getClass().getResource("1.gif"));
根據這兩個方法,基本上我們日常大部分的操作都可以進行了。
好了,我們初級的課程就到這裏,後續還有更加深入的Java打包jar內幕(高級篇)。