用Java開發程序
發布時總要考慮的問題就是怎麼在使用者的機器上裝好JRE
要考慮的問題很多
使用者有沒有能力獨自安裝JRE
使用者已有的JRE和我們需要的版本是不是一致
會不會出現版本問題
等等
使用
NET要考慮的問題就少些
現在
NET CLR似乎已經很普及了
看好多D版的Win XP都會自己安裝最新的
NET CLR
而且似乎它的安裝界面也比JRE友好些
徹底解決安裝JRE的問題的方案
就是讓我們的應用程序自己背著JRE!這樣
我們的程序就像傳統的Win
應用程序一樣
雙擊就可以執行
不用管所在的機器上是否有JRE
是什麼版本的JRE
無論怎樣
我有我自己的!要做到這一點
其實非常容易
王森在他的《Java深度歷險》(強力推薦這本書
內容少而精)的第一章就解釋了JDK
JRE
JVM之間的關系
解釋了我們執行java
exe時發生的事情
其中提到
java
exe依照一套邏輯來尋找可以用的JRE
首先查找自己所在的目錄下有沒有JRE(據王森講這樣說不確切
我沒有JDK全部的源代碼
在此無從考證)
其次查找自己的父目錄下有沒有JRE
最後才是查詢Windows的注冊表
通常我們在安裝好了JRE的機器上的任何一個目錄下都可以執行java
exe
因為它在安裝時被復制到了windows的system
目錄下
而後者無論如何都會在path環境變量中
這個java
exe最終必然會訪問注冊表來確定真正的JRE的所在地
若我們要求每一個應用程序都自帶JRE
必然不能走這條路
但
邏輯的第二條講
java
exe會在它的父目錄下查找JRE
解決方案就在這一條中
假設我們的應用程序打好了包
叫做MyApp
jar
放在MyApp的目錄下
我們在MyApp目錄下
可以執行java –jar MyApp
jar來運行我們的程序
我們安裝的是JRE
在C:\Program Files\Java\jre
下
現在
我們只需要簡單的將jre
目錄搬到MyApp目錄下
順便改個容易寫的名字比如叫jre
現在
我們的應用程序就象這樣
MyApp
MyApp
jar
Jre
Jre
目錄下的全部內容
Java
exe就在jre目錄下的bin目錄中
根據第二條邏輯
java
exe會在它的父目錄中查找jre
實驗證實
它會查找lib目錄
而lib就在jre目錄下
因此
這樣java
exe就會確定jre的所在然後正常執行java程序
不會去管我們是否安裝了JRE
注冊表中是否有注冊項這些雜事了
試一下
在命令行下進入MyApp的目錄下
假設它在C盤
將path指向MyApp下的JRE
set path=c:\MyApp\jre\bin
然後運行
java –verbose –jar MyApp
jar
加上verbose參數以確定我們確實用了這一套被搬出了家的JRE
程序可以運行
並且在命令行輸出的前幾行
可以看到
[Opened C:\MyApp\jre\lib\rt
jar]
[Opened C:\MyApp\jre\lib\jsse
jar]
[Opened C:\MyApp\jre\lib\jce
jar]
[Opened C:\MyApp\jre\lib\charsets
jar]
因此程序讀取的確實是它的私有的JRE
至此
我們似乎完成了任務
但是現在我們的私有JRE仍不完美
缺點是太大
JRE
有接近
MB
作為我們的私有的JRE
好多內容都是可以拋棄的
Jre目錄下的license都可以不要
bin下的執行文件只需要保留java
exe或者javaw
exe
lib下只要保留rt
jsse
jce
charsets幾個庫就可以了
除了i
和zi兩個子目錄外
其余的子目錄都可以不要
Zi下只需要保留自己地區的子目錄和其下的一些文件就可以
Lib下除了庫之外的屬性文件等等都要保留
這樣清理一番
JRE仍然有接近
MB
還可以繼續清理幾個庫文件裡面不需要的內容
這需要仔細的整理
會很費功夫
最好能寫出一個自動工具幫助我們整理它們
從Sun公司上下到的JMF裡面附帶的用Java寫的媒體播放器就自帶了JRE
只有幾個MB
清理過後需要運行幾遍我們的應用程序
以確保我們的JRE不缺少東西
如果我們希望能有一個程序直接啟動我們的應用程序
那就還要費些功夫
最簡單的方法是弄出一個快捷方式來
但是快捷方式的路徑不能是相對的
不方便我們安裝
我想到的方案就是用Win
程序包裝一下
在VS
NET下寫一個Win
小程序
int PASCAL WinMain( HINSTANCE hInstance
HINSTANCE hPrevInstance
LPSTR lpszCmdLine
int nCmdShow ){ STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si
sizeof(si) );
si
cb = sizeof(si);
ZeroMemory( &pi
sizeof(pi) );
// Start the child process
if( !CreateProcess(
jre\\bin\\javaw
exe
//執行的程序名
jre\\bin\\javaw
exe
jar MyApp
jar
// 帶參數的執行程序
NULL
// Process handle not inheritable
NULL
// Thread handle not inheritable
FALSE
// Set handle inheritance to FALSE
// No creation flags
NULL
// Use parent
s environment block
NULL
// Use parent
s starting directory
&si
// Pointer to STARTUPINFO structure
&pi )
// Pointer to PROCESS_INFORMATION structure
)
{ ErrorExit(
CreateProcess failed
);
} // Wait until child process exits
WaitForSingleObject( pi
hProcess
INFINITE );
// Close process and thread handles
CloseHandle( pi
hProcess );
CloseHandle( pi
hThread );}
基本上是按照MSDN文檔中的例子照搬的
將它編譯成一個EXE文件
我們的任務才全部完成
雙擊這個EXE文件
我們的程序啟動了
看起來和傳統的Win
程序沒有兩樣
JRE完全被隱藏在底層
P
S
使用了這個方案後
我用Wise Installation System制作安裝程序
發現一個非常奇怪的問題
安裝結束後
安裝程序似乎非要運行一個叫做GLJ什麼什麼
後綴是TMP的程序
還需要JVM
結果就報錯JVM
DLL找不到
安裝總是不成功
我已經禁掉了OCX / DLL / EXE自注冊和卸載支持
為什麼還不對?有誰知道是為什麼嗎?
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26180.html