Android和正在运行的OOM还剩下免费堆空间

时间:2013-07-01 14:55:13

标签: java android memory-management

我有一个运行OOM的应用程序,有足够的免费堆空间,可以在股票Galaxy S3上增长。该应用程序在其他设备上运行良好。

知道在传统的Java中,这可能是由于永久生成空间中的OOM造成的,我试着研究Dalvik如何处理这个,但找不到任何确定的东西。 Androids SDK似乎缺少MemoryUsage和ManagementFactory,所以我不能像在Java中那样得到它们。

我正在试图找出Android是否具有永久性生成空间,我可以检查其内容,我如何获得大小和免费,Dalvik是否处理与JVM不同的进入此空间的内容等。

如果这个空间不存在或者不太可能,也可以接受其他想法。

关于该应用的一些信息。运行OOM的S3正在运行4.1.2。该应用程序使用大约12-25 MB的堆,可用的最大堆大小约为45 MB。它有很多本地资源图像,以及稍后的延迟加载。我是.recylce()的位图。该应用程序每次都在大致相同的位置崩溃。我已经很好地看了一下那个崩溃的地方的代码,我没有看到任何与众不同的东西。其他设备运行此代码就好了。

1 个答案:

答案 0 :(得分:1)

在我看来,您遇到了堆碎片问题。

你在拥有足够可用空间的堆中分配1.2MB的失败。系统可能无法找到1.2MB的连续空块,因为堆完全碎片化,并且无法进一步扩大堆。

理论上,你不应该担心碎片问题而且自动GC会为你处理它..

实际上,我不止一次地看到,给系统GC提供帮助有时会获得很好的结果。

以下是解决碎片问题的一些想法:

  1. 在策略性放置的位置手动运行System.gc()。受欢迎的位置是在诸如活动onDestroy之类的大型物体的破坏期间。其他地方是在像Bitmaps这样的大型分配之前。在解码任何大位图之前,请添加手动GC。如果您想稍后减少GC的数量,可以通过查询各种堆大小函数来为有问题的内存条件添加手动测试。

  2. 更快地协助System GC免费资源。这样可以防止堆首先出现碎片。网上有很多关于如何做到这一点的材料。一些来自我的头脑:

    • 如果频繁进行小分配,请尝试采用内存重用方案,例如创建对象池,重用池中的对象而不是分配新对象。这种优化经常出现在Android适配器中(如列表视图中的视图重用)
    • 当您不需要它们时,手动将变量设置为null,以便明确地将它们与参考图形断开,并将它们标记为简易GC(同样可以明确清除数据集合)
    • 当你有大量的操作时避免使用不可变的类,比如字符串的连接,使用StringBuilder而不是常规的String
    • 完全避免终结者
    • 避免循环引用,或至少将其中一个更改为弱引用
    • 在需要时使用弱引用
  3. 您可以通过确保在仅使用其中的一小部分时堆不会增长到大尺寸来衡量您的成功程度。

    另一个想法是尝试使1.2MB的分配更小..通过使用较小的图像或在解码过程中重新缩放它们。