1. 程式人生 > >[JAVA]利用bat將jar轉變成一個可執行檔案exe

[JAVA]利用bat將jar轉變成一個可執行檔案exe

>本質

    明白話說在前頭,其實這是一種掩耳盜鈴的做法,不過在表現形式上,很像是把jar變成了一個可執行的exe檔案來執行。

    jar的執行依舊是需要JRE環境的,但這個我們可以通過其他方式來實現,這裡暫掛不表,我們留到最後去說。

    轉載請註明:[來自身披白袍的部落格:http://blog.csdn.net/shenpibaipao]

>執行前提

    首先,要保證你的jar包雙擊之後能夠執行,或是利用cmd控制檯執行下面的命令後可以執行。

javaw -jar xxxx(你的jar包)
    有時候,雙擊可能並不能執行,但通過cmd控制檯輸入上面那個命令可以執行。這個主要是因為登錄檔和系統環境變數的問題,我會在另外一篇文章裡說說這件事。

    總之,最低的執行前提是,在cmd中輸入以上命令可以執行。(當然,如果不行,看文末更一般的解決方法)

>編寫bat

    之所以選擇利用bat,是因為它在dos和windows系統下都是標準的可執行檔案,另外一個很重要的原因就是指令碼編寫簡單。我們新建一個run.bat,右鍵txt開啟,輸入以下兩行指令碼命令,儲存退出:

start javaw -jar myTest.jar
exit
    我們很容易觀察到javaw -jar myTest.jar實際上就是我們在cmd中測試過的執行jar的命令,這裡只不過套了一層bat的批處理指令碼去執行了這行命令並打開了jar檔案。

    這裡有兩個要點

  • start:啟動一個視窗
  • exit:此處作用是退出當前cmd視窗
     之所以要加上一個start
命令,原因在於:如果不加start命令,當我們執行這個bat之後,由於這個jar還處在執行狀態,指令碼"並不能執行"到exit這一行,於是一個又醜又黑的cmd控制檯框就會橫貫在桌面上而不會自動關閉,就很煩。而加上了start,實際上我們建立了一個視窗,在這個視窗中再執行javaw -jar myTest.jar——這一行的主要動作是建立新視窗,執行完後並不會關心這個窗口裡在執行什麼東西,於是指令碼就走到了下一行的exit,最終該這個黑色的控制檯視窗就會被自動幹掉了。

     這一點在很多利用bat啟動jar的教程裡都沒有提到,算是一個小小的trick

>編寫可執行檔案exe

    隨便開啟一個C語言編譯器,比如我用了大小為50MB的DevC++。Ctrl+New一個檔案,輸入以下內容:

#include <stdlib.h>

int main(int argc, char** argv) {
	system("run.bat");
	return 0;
}
    沒什麼好說的,就是用系統命令去啟動剛剛的那個run.bat檔案,編譯成exe即可。需要注意的是相對路徑的問題。

    *在我以上給出的程式碼中,jar、bat、exe檔案都在同一個資料夾下。(很顯然我寫的都是同級相對路徑,你們可以自己加上自己的相對路徑)

    需要注意的是,執行exe檔案時可能會報缺失libgcc_s_dw2-1.dll

    可以到下面這個地址去下載,並放到同級目錄下:

>執行測試

   於是,我們現在點選執行exe檔案,其真正執行過程會變成這樣:

    [exe]->[run.bat]->"javaw -jar myTest.jar"->[jar]

    某種意義上就把jar偽裝成了一個exe來執行。到這裡,這個教程基本上就算完工了,很簡單,自己就能完成,而不需要用到exe4j之類的軟體。


>更一般的解決方法

   在C語言中,完全可以通過system指令去執行shell或者dos,那麼我們為什麼要用bat呢?因為更方便修改。

   配過java環境的人都知道這是一個多麼麻煩的東西,不僅僅是環境變數,在windows系統下還需要考慮登錄檔的問題。像我在文章開頭提到的:用cmd能執行jar當雙擊jar卻無法執行就是一一個登錄檔的問題。其次,使用bat這種指令碼檔案更便於我們動態修改執行指令。因為exe一旦編譯,就很難去修改了,除非重新編譯一遍。

   換句話說,這裡的exe就相當於一個殼,一個把內部實現偽裝過後的、對外部使用者暴露的殼。

    還有一個大麻煩,怎麼解決JRE的問題

    其實也不難,我們都拿C#寫過桌面應用,但實際上C#本身也是需要.net支援的,只不過微軟幫我們搭配好了這個.net環境。

    微軟既然不能幫我們把JRE搭配好,那我們就手動來吧。拿JRE8舉例,Oracle官方下載的壓縮後的exe檔案是70MB,實際安裝完的大小是170MB,說大不大說小也不小。

    首先,我們在我們要釋出的的jar軟體中都打包一份JRE檔案。

    當我們在執行javaw -jar xxxx 時,實際上我們用的都是這個JRE資料夾中的.\jre8\bin\javaw.exe。只不過在配好環境變數PATH的系統中,我們在cmd中直接輸入javaw -jar xxx,系統會通過PATH給出的地址,去執行shell搜尋相關的javaw.exe檔案。

    現在那麼我們寫批處理檔案的時候,不預設通過shell去搜PATH地址下的javaw,而是自己給出它的地址(假設jre8資料夾與bat檔案同級):

./jre8/bin javaw -jar (你的jar)
    但是這樣還遠遠不夠,這麼寫只是把javaw.exe給找到了而已,配置java系統環境變數的時候,別忘了還有一個CLASSPATH。

    這個東西主要是在JVM啟動的時候去做類載入的,簡單來說就是給你的jar檔案找執行庫。其一般取值為:

.;%Java_Home%\bin;%Java_Home%\lib\dt.jar;%Java_Home%\lib\tools.jar
    其中%Java_Home%是jre8資料夾的絕對地址。其搜尋了三個地方:
  • .; 也就是當前目錄下的所有jar檔案;
  • dt.jartool.jar
那隻要知道了這兩點,我們在bat檔案裡手動指定一下也是ok的:
set Java_Home = ./jre8
start ./jre8/bin/javaw -classpath .;%Java_Home%/bin;%Java_Home%/lib/dt.jar;%Java_Home%/lib/tools.jar -jar myTest.jar
exit

     現在,只要帶著jre8這個資料夾,你的jar就可以假裝自己是一個exe,滿世界撒丫子亂跑了。