熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

分享:讓Java程序帶著jre一起上路

2013-11-23 19:02:35  來源: Java核心技術 

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