JER瘦身方法
本回主在描述精簡一個Java應用的實際步驟,選取了ApoDefence這個小型的Java即時戰略游戲作為用例。 該作者信息可以在http://home.arcor.de/newbielein/獲得,這是一個德文網頁,作者也提供了其它一些小型Java游戲的展示,比如:
圖片看不清楚?請點擊這里查看原圖(大圖)。
有興趣的可以下載作為參考。
ApoDefence?? 是一個Java制作的2D即時戰略游戲,游戲主題是本國要塞的加固及本國城堡的防護,雖然作者所提供的功能對比商業化游戲遠不夠完全,但是即時戰略游戲的基本要素,如小地圖,點選對象,建筑的搭建、修理、破壞、計時,建筑升級,多兵種協作,敵我互動及地圖編輯都已經在由此游戲中展現出來,應該這個程序說對于開發Java即時類游戲而言是一個不錯的參考范例。
ApoDefence主要文件有兩部分,一是ApoDefence.jar本身,一是levels文件夾下的腳本地圖,兩者累計大小為734KB。
應該說,如果它永遠只有這么大,將他放到同人游戲站點上,下載量是絕不會輸給其他語言開發的同類游戲的。
游戲界面1:
游戲界面2:
圖片看不清楚?請點擊這里查看原圖(大圖)。
但遺憾的是,這個游戲是Java開發的,如果沒有動輒數十兆的虛擬機支持,它是很難跑得起來的。
試問你看到這么一個小游戲,記住,也僅僅是個小游戲,它似乎很好玩,卻需要下載十幾甚至幾十兆的安裝程序,你還會有興趣去嘗試嗎?我相信大多數人的答案會是否定的,所以,我開始試著精簡它。
第一步:整理你的RT.JAR文件
我們都知道,JRE的完整版體積是很大的,在其文件夾內充斥著無數的dll,jar及properties配置文件,但要說到其中那個文件最大,最占用空間,則首推rt.jar文件莫屬。
以JRE1.6中的rt.jar為例,僅它一個jar,便占用了將近46MB的硬盤空間,這無疑是種壟斷,嚴重擠壓了其它jar同類的生存空間~~~
圖片看不清楚?請點擊這里查看原圖(大圖)。
前兩天我在Blog發過一篇文章,講的就是這件事(精簡jre體積),我提供了一個名為GreenJVMMake.jar的6KB小程序,它能夠準確的記錄每次啟動Java程序所調用類與rt.jar中類的對應關系,并且在程序執行結束后生成一個僅攜帶調用類的rt.jar。
那么,我們要開始精簡rt.jar了。
首先,我們制作一個簡單的bat批處理文件,內容如下:java?? -jar GreenJVMMake.jar -t da -i ./ApoDefence.jar -o?? ./
為的是調用ApoDefence.jar圖形程序,并將精簡后的rt.jar在本地輸出。
我們可以看到,隨著我們的操作,所有被調用過的類都被記錄下來了,事實上由于組件大多數都會重用的關系,只要運行幾個典型界面,就可以把整個程序使用到的class全部打包進來了,而不必一直玩到通關。
圖片看不清楚?請點擊這里查看原圖(大圖)。
現在我們來看看成果吧,一個原始大小將近46MB的“怪物”,現在在這個Swing游戲環境中,還剩下多少呢?20MB嗎?10MB嗎?不,比那要小得多,答案是僅有不足3.2MB了。
圖片看不清楚?請點擊這里查看原圖(大圖)。
這么小的庫能夠跑得起來這個Swing游戲嗎?我們可以先在本機試試看。
圖片看不清楚?請點擊這里查看原圖(大圖)。
就結果來看,答案似乎是肯定的,我們精簡成功了。但事實果真如此嗎?未必。我們將程序發布到一臺從未配置過Java環境的機器看個究竟。
PS:本示例使用自制的GreenJVM作為虛擬機引導程序,詳細見:http://blog.csdn.net/cping1982/archive/2008/08/21/2806598.aspx
圖片看不清楚?請點擊這里查看原圖(大圖)。
我們可以清楚地看到,雖然開始啟動后已經載入了作者的丑陋嘴臉~|||……但GreenJVM卻同時提示給我們一個Exception,顯示找不到sun.font.StandardGlyphVector類,但我們在本地調試得好好的啊,究竟為什么呢?
其實原因很簡單,就在于我們的JRE是針對A系統環境而配置的,而并非B系統。
大家都知道,無論是JRE或者我們開發Java程序時,為了最大限度發揮Java跨平臺特性,都會對不同的系統采取不同操作,從而提高本地環境下Java執行效率。
但是,當我們利用GreenJVMMake.jar進行rt.jar精簡后,則只會獲得本機環境下需要的類,卻并非所有環境下都通用的類,異常產生的原因也在于此。那么我們應該怎么辦呢?
其實很好解決,第一、由于我們使用的是自帶JRE,決不會存在版本沖突問題,無論調用方式怎樣,最終的結果,絕對是特定版本產生的,也就是不可能存在針對版本優化而缺少類庫的顧慮。第二、事實上能夠針對不同環境的配置變更并不多,要說最常見的,那就是語言與字體。比較典型的就是我們剛才所見的font包異常,這類異常大多是由現有?? Java字庫對本地環境的不支持所產生的,那么針對在不同環境使用的程序,我們在精簡時可以刻意的保留下所有font及所有如zh_cn、en等針對不同語言所定制的對應類(英文程序則沒必要保留所有語言支持),這樣雖然程序體積比之前略大些,卻可以從根本上解決問題。
現在,我替精簡的rt.jar重新拷貝所有的font支持類(這部分我在GreenJVMMake.jar中添加了完整保留指定庫的功能,由于改動太少暫時沒有發布,自己ctrl+c和ctrl+v也不麻煩)。
替換后的精簡rt.jar大小如圖:
第二步:刪減不必要的exe,dll及其它一切配置文件。
這步說簡單也簡單,說麻煩便麻煩,簡單的是舉凡rt.jar中不調用的,除了jvm.dll(它調用一切),我們盡管刪掉即可;麻煩的是目前為止還沒有一個工具提供了這樣的功能(考慮寫一個),現在我們只能依據經驗來判定這些文件是否會被rt.jar調用了,這部分我準備寫再下回時說,先賣個關子。但有一點最基礎的大家可以注意一下,那就是通常這些文件名會有和類名互相對應的部分。
第三步:壓縮精簡后的JRE
這時有兩類方式可供選擇。
一、使用Install4J等工具制作精簡JRE。
我這里建議使用Install4J,這是目前為止對Java軟件支持最全面的安裝包制作工具,我個人目前所使用的是4.1.4版。
我們以Install4J為例,直接通過選擇[Create?? a JRE Bundle] ,創建一個自定義的JRE包。
選擇精簡后的JRE所在路徑,版本,及擴充名(Install4J識別用)。
圖片看不清楚?請點擊這里查看原圖(大圖)。
此時的Install4J對JRE來說,會有兩種不同的壓縮方式,一是針對JRE1.5以下版本的直接壓縮,二是針對JRE1.5以上版本的pack200壓縮jar,再二次壓縮成JRE包。
當我們使用JRE1.5以下版本方式壓縮JRE包時,通常不會有任何問題,因為這時Install4J只是單純的壓縮一個gz格式文件。
如上圖所示,針對JRE1.5以下版本進行JRE壓縮成功,最后生成的文件將位于Install4J目錄下jres文件夾中,本例生成的JRE文件大小約5MB。
而當我們以JRE1.5以上版本壓縮JRE時,問題就來了,因為此時Install4J將調用pack200進行jar壓縮。
對一個完整的JRE打包來說,擁有pack200相關功能當然不是問題,可在使用精簡的JRE時,卻變得不一定了。
圖片看不清楚?請點擊這里查看原圖(大圖)。
瞧,剛才還能正常運轉的Install4J,此刻卻罷工了。理由很簡單,我們的精簡包中沒有打入pack的類支持,是的,運行Install4J的JRE1.5以上版本打包不光需要Pack200.exe文件,同時需要rt.jar中的類庫支持。
沒辦法,我們制作一個完整調用pack類庫的小程序,而后以此生成僅有依賴庫的rt.jar,合并打包進自定義的rt.jar中,再次運行程序。OK,通過了。
圖片看不清楚?請點擊這里查看原圖(大圖)。
經過Install4J打包的jre1.5以上版本jre能夠壓縮得相當厲害,我們原本將近10MB的文件經其壓縮整理后只有2MB多一點。
但是Install4J畢竟是一個收費軟件,況且現在的環境下流行綠色軟件,也就是所謂的免安裝無插件不修改注冊表或其它系統文件的程序……畢竟我們有時也希望能將Java程序作為一個綠色軟件進行發布。
二、使用7-Zip等工具制作精簡JRE。
現在,我們以7z格式制作一個jre壓縮包。
首先,我們學習Install4J的方法,先將所有jar進行pack200打包,由于pack200是針對jar定制的壓縮程序,所以能最大限度的減小jre中文件體積。
由于本示例使用GreenJVM作為jar引導程序,所以包名后綴命名為[pack200],當GreenJVM初始化時將自動調用unpack200.exe解壓文件所在目錄及子目錄下所有[pack200]后綴的文件。
其實,我們使用壓縮工具對JRE文件夾進行壓縮,本例中我們使用7-zip進行壓縮。
7-zip是一個源碼開放的基于lzma方式的免費軟件,單就文件壓縮率而言,較rar格式更高,下載地址:http://www.7-zip.org/
圖片看不清楚?請點擊這里查看原圖(大圖)。
此后我將將得到一個jre,現在這個總體積約5MB的jre包,就是最終可以執行此Swing游戲的環境了(相較于Install4J壓縮后的JRE包而言,這個JRE壓縮文件還是大了,利用某些機制還可以壓得更小,下回介紹)。
無論我們采取那種機制,這個JRE最終發布版都會被維持在5MB以內。
第四步,打包發布。
1、直接進行壓縮打包
這點其實沒什么可說的,如果你使用GreenJVM制作的綠色Java程序,那么你只需把用到的程序連帶精簡后的JRE都丟給用戶就好。雙擊exe文件運行我相信大部分使用過電腦的人還是明白的……
另外有一點需要補充說明,就是同種壓縮方式二次壓縮將很難使文件再度縮減,比如本例我們以7z格式打包jre,那么如果針對整個應用制作再次壓縮文件則選用rar格式更合適。
2、使用Install4J進行打包發布
比較大多數Java開發的程序而言,上面這個綠色發布版的體積可說是相當小了,已經能滿足絕大多數Java游戲的需要(除了沒聲音,因為原游戲沒調用),但是對比本地環境開發的程序來說依舊太大,用戶并不一定便會接受,這時我們為了讓他更小一些,單純的壓縮已經不能派上用場,非借助安裝工具的多重壓縮精簡不可了。
依舊使用Install4J,它的視圖安裝方式極為簡單,正宗的傻瓜式“下一步”就可以搞定,時間關系這里不作詳細說明,直接跳到設定媒體文件模式。
由于此示例基于windows系統開發,所以僅設定windows平臺支持。
圖片看不清楚?請點擊這里查看原圖(大圖)。
經過一系列下一步后,選擇我們制作的JRE,靜態綁定。
最后,我們選擇構建一個Windows平臺下的安裝程序。
圖片看不清楚?請點擊這里查看原圖(大圖)。
看吧,這就是最終的結果。
一個僅僅1.25MB的Swing即時戰略游戲,試問如果我們不說這是Java開發的程序,又有幾個人能想得到連虛擬機帶執行程序打包后也僅僅1.25MB呢?而且事實上,它還可以變得更小,乃至精簡到1MB之內。(留待下回說明)
現在,我們將它安裝到沒有JRE的計算機上去看看結果吧。
圖片看不清楚?請點擊這里查看原圖(大圖)。
圖片看不清楚?請點擊這里查看原圖(大圖)。
炮彈照打,獅子照跑~~~完全OK。
那么下回,我們將進一步尋找究竟有哪些因素限制了JRE的體積,并進一步解放JRE。
(由于Install4J打包有一些細節準備下回分解,所以安裝程序暫時不發,透露一點,壓縮的JRE要想正常使用Install4J發布,還需補充一些文件,可參見Install4J正常安裝時釋放在temp中的某些東西~)
總結
- 上一篇: 用css画一个原型里有一个对号或者叉叉的
- 下一篇: Java环境搭建及JAVA-jdk环境变