2013-03-09 48 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