Out momory 一陣天旋地轉內存又溢出了。在手機上這種痛苦經常都有,套一句俗話在手機上用內存必須勒緊褲腰帶。
雖然現在pc內存上G都不奇怪,可是在手機上卻只能以K來記,可能某位同志會馬上跳出來說也有上M的,記住中國還不富大多數手機都是低端手機。寫手機程序讓我仿佛回到了DOS時代(自我安慰一下那個時代也煉出了不少高手說不定我是下一個)。言歸正傳做內存優化可以歸結為以下幾種方法。代碼優化,圖片優化,第三方工具優化等…
一.代碼優化
內存會溢出肯定和代碼逃不了關系,99.99%學java的人都知道垃圾回收器是java的一大優點並據此來嘲笑C++。顯然這個特性為代碼編寫者省了不少事,但這個特性卻帶來了不少隱患。舉個例子在游戲當中經常有不同場景的切換,如從游戲邏輯退到主菜單邏輯,對游戲邏輯對象的態度很多人會選擇忘記等待垃圾回收器來收屍^_^。乍看之下似乎並無不妥垃圾回收器會來善後。實際上垃圾回收器並非實時的,它不像C++的Delete語句馬上釋放不用的內存。當從游戲邏輯切換到主菜單邏輯這時兩個對象同時存在很可能這時內存就不夠用了。讀到這裡很多人會發現實際上垃圾回收器在j2me上並不怎麼好用,從一個角度上來講在j2me上所有垃圾必須由手工釋放,除簡單類型以外所有對象都必須顯式地置空例如 imgs=null; 實際上java提供了一個不錯的工具用來查找內存溢出,java.lang.Runtime.freeMemory() 。它可以返回當前的剩余內存數,將它適當的安放在代碼中可以有效的監測內存使用狀況。
很大一部份的j2me程序員之前都是從事pc軟件開發工作,充裕的內存掩蓋了許多寫代碼的不良習慣。如下所示:
//a 不為空
a=new Logic();
很多人可能對此有異議,他們會認為新的對象會把舊的對象沖掉並且釋放內存。這裡面包含兩個問題:1. 該段代碼是先創建對象然後再進行賦值操作的,也就是說在這期間有兩個對象同時存在這就很可能會產生溢出。2. 這樣做也會妨礙垃圾回收器的工作。
較好的寫法如下:
a=null;
a=new Logic();
雖然麻煩了點但在j2me中還是必要的。接著看下例。
drawString("游戲
二. 圖片優化
J2ME的內存殺手無疑非圖片莫屬,一張3k的圖片可以占用20多k的內存不信大家把load前後的內存剩余打印出來對比看看。所以防止內存溢出最直接的辦法就是從圖片入手。
1.圖片壓縮: 多數人馬上會想到這個辦法。不錯這個辦法是最有效的。在photoshop裡圖片制作完成後不要選擇 "存儲為",而是選擇 "存儲為 web 所用格式" 可以根據裡面的選項進行壓縮,特別是顏色這一項越小越好不過相應的圖像會有所失真。不要認為這樣就完了。
實際上該圖片還可以再次壓縮,在網上有許多類似的工具。推薦一款可以壓縮png格式的軟件 xat.com Image Optimizer 效果不錯。經常都有 70% 的壓縮率且圖像不會失真。
假如你有多張規格一樣的圖片,那麼建議你把它做成一張長條圖片。有兩個原因:
1、這樣節省存儲空間和內存空間。大家可做個試驗將10張圖片的內容放在一張當中對比看看文件大小有沒有變化。
2、10張圖片需要10個image 對象需要進行10次io操作浪費時間不說還浪費內存。當筆者發現這個好處時興奮地把所有圖片都存成一張,吱地一聲內存又溢出了...原因想必大家也知道!!圖片太大了不要把不同界面的圖片整合在一起否則經常會得不償失。
作圖時還有一些細節需要注意,顏色數量,分辯率,圖像模式(最好是索引顏色),畫布大小都會影響到圖片大小。
三.工具優化
誰都知道混淆器是用來保護代碼的以加大反編譯的難度(個人認為這是在嘲笑程序員的智商)。實際上用它來優化程序也是不錯的選擇,至少有兩點好處:1、 壓縮程序大小。一個60k的程序經常可以壓掉10k左右。10k的空間對於寫低端手機的程序員簡直是雪中送碳,多少超過64k限制的游戲都受過它的恩惠;2、節省內存空間。用腳去想也想得出來代碼少了內存裡的代碼段自然就短了。
根據經驗很多人都會用jb自帶的混淆器RetroGuard,實際上它效果並不怎麼好。推薦使用proguard 在 http://sf.net 可以免費下載,它可以比retroguard 多壓縮3至4 k 以上而且安全性更好。