2013-03-09 56 views
1

我以爲檢查Runtime.getRuntime().freeMemory()會做,但是下面的測試似乎表明它是沒有用的:如何預防的OutOfMemoryError通過檢查堆狀態

List<Byte> listDebug = new ArrayList<Byte>(); 
Log.d("Free memory", String.format("%1$.2f", (float)Runtime.getRuntime().freeMemory()/(1024*1024))); 
for (int i = 0; i < 100; i++) { 
    try { 
     listDebug.addAll(Arrays.asList(new Byte[1024 * 100])); 
     Log.d("Free memory", i + ":" + String.format("%1$.2f", (float)Runtime.getRuntime().freeMemory()/(1024*1024))); 
    } catch (Exception ex) { 
     Log.d("Free memory", ex.getMessage()); 
    } 
    catch (Error e) 
    { 
     Log.d("Free memory", e.getMessage()); 
    } 
} 

輸出如下:

03-09 03:16:11.267: D/Free memory(3860): 1.30 
03-09 03:16:11.277: D/Free memory(3860): 0:1.25 
03-09 03:16:11.287: D/Free memory(3860): 1:2.63 
03-09 03:16:11.298: D/Free memory(3860): 2:3.86 
03-09 03:16:11.298: D/Free memory(3860): 3:3.08 
03-09 03:16:11.317: D/Free memory(3860): 4:4.85 
03-09 03:16:11.317: D/Free memory(3860): 5:4.06 
03-09 03:16:11.317: D/Free memory(3860): 6:3.28 
03-09 03:16:11.367: D/Free memory(3860): 7:7.84 
03-09 03:16:11.367: D/Free memory(3860): 8:7.06 
03-09 03:16:11.367: D/Free memory(3860): 9:6.27 
03-09 03:16:11.387: D/Free memory(3860): 10:7.84 

freeMemory()返回最高數字時,測試應用程序在擴展列表11次後崩潰。我深感困惑。我的測試代碼是否存在根本性缺陷或freeMemory()java.lang.OutOfMemoryError完全不相關?

回答

2

簡單的答案是它有點不相關。所述javadoc說:

返回

近似量的空閒存儲器,以字節爲單位。

上都安有更多的細節,因此解決這一一些其他問題:

你可以試着用一些誤差使用的值(例如,將85%的內存使用量視爲無空閒內存),但最好的方法是在發生問題時簡單地捕獲並相應調整行爲(re使用較少內存密集型方法啓動進程,清除內存中的其他內容並重試相同進程,完全跳過該進程,提醒用戶,放棄等)。

+0

謝謝。什麼是防止OutOfMemoryError的正確方法? – Hong 2013-03-09 15:40:58

+0

@洪:使用更少的內存? :-)不要試圖檢測和防止這個異常,而應該在那個時候捕捉並處理它。您還應該查看您正在執行的流程,並對其進行調整,以便一次處理更少的數據,或者更高效地工作以減少錯誤的可能性。 – user113215 2013-03-09 15:52:38

+0

我應該指出,在發佈這個問題之前,我閱讀了大量關於freeMemory()和OutOfMemoryError的文章。捕捉OutOfMemoryError不是一個選項,因爲在捕捉到OutOfMemoryError時防止崩潰爲時已晚。該應用程序接收流數據並進行處理。在大多數情況下,它只有幾MB。我認爲在列表中存儲幾MB數據不會成爲問題。我現在可以看到的唯一選擇是將數據序列化到存儲。 – Hong 2013-03-09 18:21:35