1. 程式人生 > >讓Java程式自帶JRE執行

讓Java程式自帶JRE執行

 用Java開發程式,釋出時總要考慮的問題就是怎麼在使用者的機器上裝好JRE。要考慮的問題很多:使用者有沒有能力獨自安裝JRE,使用者已有的JRE和我們需要的版本是不是一致,會不會出現版本問題,等等。使用.NET要考慮的問題就少些。現在.NET CLR似乎已經很普及了,看好多D版的Win XP都會自己安裝最新的.NET CLR,而且似乎它的安裝介面也比JRE友好些。徹底解決安裝JRE的問題的方案,就是讓我們的應用程式自己揹著JRE!這樣,我們的程式就像傳統的Win32應用程式一樣,雙擊就可以執行,不用管所在的機器上是否有JRE,是什麼版本的JRE,無論怎樣,我有我自己的!要做到這一點,其實非常容易。    王森在他的《Java深度歷險》(強力推薦這本書,內容少而精)的第一章就解釋了JDK,JRE,JVM之間的關係。解釋了我們執行java.exe時發生的事情。其中提到,java.exe依照一套邏輯來尋找可以用的JRE,首先查詢自己所在的目錄下有沒有JRE(據王森講這樣說不確切,我沒有JDK全部的原始碼,在此無從考證);其次查詢自己的父目錄下有沒有JRE;最後才是查詢Windows的登錄檔。
    通常我們在安裝好了JRE的機器上的任何一個目錄下都可以執行java.exe。因為它在安裝時被複制到了windows的system32目錄下,而後者無論如何都會在path環境變數中。這個java.exe最終必然會訪問登錄檔來確定真正的JRE的所在地。若我們要求每一個應用程式都自帶JRE,必然不能走這條路。但,邏輯的第二條講,java.exe會在它的父目錄下查詢JRE,解決方案就在這一條中。

    假設我們的應用程式打好了包,叫做MyApp.jar,放在MyApp的目錄下。我們在MyApp目錄下,可以執行java –jar MyApp.jar來執行我們的程式。我們安裝的是JRE 1.5,在C:\Program Files\Java\jre1.5.0下。現在,我們只需要簡單的將jre1.5.0目錄搬到MyApp目錄下,順便改個容易寫的名字比如叫jre。現在,我們的應用程式就象這樣:
MyApp
       MyApp.jar
       Jre
              Jre1.5.0目錄下的全部內容
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 1.5有接近70MB,作為我們的私有的JRE,好多內容都是可以拋棄的。Jre目錄下的license都可以不要,bin下的執行檔案只需要保留java.exe或者javaw.exe,lib下只要保留rt,jsse,jce,charsets幾個庫就可以了。除了i386和zi兩個子目錄外,其餘的子目錄都可以不要。Zi下只需要保留自己地區的子目錄和其下的一些檔案就可以。Lib下除了庫之外的屬性檔案等等都要保留。這樣清理一番,JRE仍然有接近50MB。還可以繼續清理幾個庫檔案裡面不需要的內容,這需要仔細的整理,會很費功夫。最好能寫出一個自動工具幫助我們整理它們。從Sun公司上下到的JMF裡面附帶的用Java寫的媒體播放器就自帶了JRE,只有幾個MB。

    清理過後需要執行幾遍我們的應用程式,以確保我們的JRE不缺少東西。
如果我們希望能有一個程式直接啟動我們的應用程式,那就還要費些功夫。最簡單的方法是弄出一個快捷方式來,但是快捷方式的路徑不能是相對的,不方便我們安裝。我想到的方案就是用Win32程式包裝一下。在VS.NET下寫一個Win32小程式:
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.
            0,                // 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檔案,我們的程式啟動了,看起來和傳統的Win32程式沒有兩樣,JRE完全被隱藏在底層。

P.S. 使用了這個方案後,我用Wise Installation System製作安裝程式,發現一個非常奇怪的問題,安裝結束後,安裝程式似乎非要執行一個叫做GLJ什麼什麼,字尾是TMP的程式,還需要JVM,結果就報錯JVM.DLL找不到。安裝總是不成功。我已經禁掉了OCX / DLL / EXE自注冊和解除安裝支援,為什麼還不對?有誰知道是為什麼嗎?

相關推薦

Java程式JRE執行

 用Java開發程式,釋出時總要考慮的問題就是怎麼在使用者的機器上裝好JRE。要考慮的問題很多:使用者有沒有能力獨自安裝JRE,使用者已有的JRE和我們需要的版本是不是一致,會不會出現版本問題,等等。使用.NET要考慮的問題就少些。現在.NET CLR似乎已經很普及了,看好多

java程式在linux上執行

最近需要將寫的程式放到linux上執行,可始終不得要領,經過反覆折騰,終於弄好了 由於所用linux上已經安裝了jdk,就沒有安裝jdk這一部分了,直接從環境變數說起 首先找到jdk所在位置,可以通過 whereis java命令查詢 然後,配置環境變數 JAVA_HOME

java程式在後臺一直執行(例如putty關閉後後臺程式繼續執行

在linux系統下如何使一個程式在後臺一直執行呢?很多人使用&結尾的命令形式,但是如果沒有守護程序的話,即使這樣,在終端關閉時程式也會終止執行。這時候就得使用nohup命令了。      例如,如果在終端中執行java -jar xxx.jar&命令,當終端

java程式在Linux後臺執行

遇到需要在Linux上面跑一個server,但是用ssh上去執行server.java程式再退出ssh,那個程式就會關閉,所以想到要讓它像一個服務一樣一直跑在Linux上面,所以找到了這個命令:nohup java Server &結尾的 & 符號代表這個程式不會受到ctrl+c的影響,依

怎樣將自己編的java程式移植到手機上執行執行編經典“Hello World!”

用JBuilder製作jar檔案時,選擇jad版本資訊的時候,應該準確的填寫。JBuilder9製作Midlet Suit jar時的MIDP的預設值是2.1,CLDC的預設值是1.1。 n73 Java:MIDP2.0、CLDC 1.1、3D API、PIM API、 5610xm Java MIDP 2

java程式釋出之jrejava程式打包成exe可執行安裝包以便安裝程式

Java開發程式,釋出時總要考慮的問題就是怎麼在使用者的機器上裝好JRE。要考慮的問題很多:使用者有沒有能力獨自安裝JRE,使用者已有的 JRE 和我們需要的版本是不是一致,會不會出現版本問題,等等。使用.NET要考慮的問題就少些。現在.NET CLR似乎已經很普及了,看

java程式執行在沒有java虛擬機器的windows系統上

首先我們使用eclipse直接匯出的jar包。在該專案中右鍵選擇Export -->java資料夾中的 JAR file --下一步--在JAR flie出選擇JAR包檔案輸出路徑此時不要直接finish,而是點選下一步,在下一步看到mian class的時候一定要選擇mian class指定執行的類

Java執行緒池Executors.newFixedThreadPool

  執行緒池的基本思想還是一種物件池的思想,開闢一塊記憶體空間,裡面存放了眾多(未死亡)的執行緒,池中執行緒執行排程由池管理器來處理。當有執行緒任務時,從池中取一個,執行完成後執行緒物件歸池,這樣可以避免反覆建立執行緒物件所帶來的效能開銷,節省了系統的資源。    在Jav

如何java程式脫離控制檯執行

最後,發現原來解決辦法相當easy:將java命令改為javaw命令!這個命令經常在工作管理員裡發現,卻一直沒留意過,今天才發現它是這般用法,不過這個命令不像java樣有幫助資訊,只好看看官網的解釋: The javaw command is identical to java, except tha

Java程式設計師別停在35歲,如何Java程式設計師走的更遠

但是由於程式設計師工作的特性,可能從30歲開始,很多人就已經花白頭髮,可能除了考慮那些複雜的業務邏輯實現以外,就是考慮未來的路應該如何前進了。 看看下面這個曲線,可能很多行業都是這樣,到了一定的年齡,人的價值體現就開始慢慢的下降了,只是程式設計師的時間更短一點。   &n

Java 程式設計師更加高效的開發工具

一、常用開發工具 作為一名 Java 程式開發人員,可選擇的整合開發環境 IDE(Integrated Development Environment)非常多,這得益於 Java 是一門開源語言。 有開源免費的;有商用收費的。 如何選擇一款適合自己的整合開發環境,亦

java程式在eclipse上執行報錯解決方法:Exception in thread "main" java.lang.NoClassDefFoundError:

最近在Linux上的eclipse中執行java程式出現了這樣的錯誤,弄了很久用了以下三種方法終後終於成功運行了,分享下,希望能幫助到大家。 Linux執行java程式提示錯誤: Exception in thread "main" java.lang.NoClassDefFoundEr

netbeans(java資料庫的建立和包的匯入 mac系統

這邊通過netbeans自帶資料庫來建立一個數據庫並且通過sql語句去連線資料庫。 不需要xampp,netbeans自帶一個數據庫來連結。下面是步驟詳解 PART1 . 通過視窗標籤來找到service服務選項dakai 找到java DB ,滑鼠右鍵 建立新

使用EXE4J將Java程式打包成可執行程式(.exe檔案)教程

作者:翁鬆秀 使用EXE4J將Java程式打包成可執行程式(.exe檔案)教程 [TOC] 由於公司需要做一個對資料庫伺服器的監控程式,用的swing來實現的一個java桌面應用程式,所以需要將做好的監控程式打包成.exe檔案,以便監控人員配置監控資訊。所以研究了一下如何

jdk執行緒池框架ThreadPoolExcutor原始碼分析

一、前言   JUC這部分還有執行緒池這一塊沒有分析,需要抓緊時間分析,下面開始ThreadPoolExecutor,其是執行緒池的基礎,分析完了這個類會簡化之後的分析,執行緒池可以解決兩個不同問題:由於減少了每個任務呼叫的開銷,它們通常可以在執行大量非同步任務

myeclipse中將java程式打包成可執行jar包

一:java專案打包 1,選擇要打包的工程,右鍵,選擇export,如下圖所示: 2,選擇java檔案下的 Runnable JAR file ,點選Next,如下圖所示: 3,進行配置,配置包含main函式的類,配置JAR包輸出位置 Launc

程式成長之路_引入小程式icon 和 引用阿里圖示(四)

上篇我們已經成功填加tabBar,那麼我們這篇就講解一下 引用圖示icon,小程式裡有自己的圖示供大家使用,但是圖示有限,有很多都滿足不了我們的需求。這次呢 給大家介紹一下阿里圖示,裡面有大量的圖示供你選擇, 下面我就給大家介紹兩種引用icon的方法 , 引用小程式自帶

java時間類用法例項 Date,Timestamp,DateFormat

我們將以Java自帶的時間日期類和其中的處理函式進行分析。 一、與時間日期有關的類。   java.util.Date。實現類,其物件具有時間、日期元件。   java.util.Calendar。抽象類,其物件具有時間、日期元件。   java.sql.Date。實現類,

IntentService——工作執行緒的服務

一、概念IntentService 是繼承自Service用來處理非同步任務的類,其內部有一個工作執行緒來處理耗時操作。當任務完成後,IntentService會自動停止,不需要我們手動去結束。如果多次啟動IntentService,那麼每一個耗時任務會以工作佇列的方式在In

34、有人說“Lambda能Java程式慢30倍”,你怎麼看?

在上一講中,我介紹了 Java 效能問題分析的一些基本思路。但在實際工作中,我們不能僅僅等待效能出現問題再去試圖解決,而是需要定量的、可對比的方法,去評估 Java 應用效能,來判斷其是否能夠符合業務支撐目標。今天這一講,我會介紹從 Java  開發者角度,如何從程式碼級別判斷應