android - 尽管可用内存可用,但 OutOfMemory 错误

标签 android bitmap jvm android-3.0-honeycomb dalvik

我看到了一个非常奇怪的问题。本质上,即使显然有大量内存,有时大型位图内存分配也会失败。有许多帖子似乎提出了类似的问题,但它们都与 pre-honeycomb android 有关。我的理解是图像现在分配在堆上,而不是一些外部内存。无论如何,请看下面的日志:

    10-14 13:43:53.020: INFO/dalvikvm-heap(31533): Grow heap (frag case) to 40.637MB for 942134-byte allocation
    10-14 13:43:53.070: DEBUG/dalvikvm(31533): GC_FOR_ALLOC freed 126K, 11% free 41399K/46343K, paused 31ms
    10-14 13:43:53.130: DEBUG/dalvikvm(31533): GC_FOR_ALLOC freed 920K, 13% free 40478K/46343K, paused 30ms
    10-14 13:43:53.180: DEBUG/dalvikvm(31533): GC_FOR_ALLOC freed 1026K, 13% free 40479K/46343K, paused 30ms
    10-14 13:43:53.250: DEBUG/dalvikvm(31533): GC_FOR_ALLOC freed 931K, 12% free 41193K/46343K, paused 31ms
    10-14 13:43:53.250: INFO/dalvikvm-heap(31533): Grow heap (frag case) to 41.313MB for 1048592-byte allocation
    10-14 13:43:53.280: DEBUG/dalvikvm(31533): GC_FOR_ALLOC freed <1K, 11% free 42217K/47431K, paused 31ms
    10-14 13:44:01.520: DEBUG/dalvikvm(31533): GC_CONCURRENT freed 3493K, 15% free 40646K/47431K, paused 3ms+9ms
    10-14 13:44:08.130: DEBUG/dalvikvm(31533): GC_EXPLICIT freed 16461K, 47% free 25527K/47431K, paused 3ms+6ms
    10-14 13:44:09.150: DEBUG/dalvikvm(31533): GC_FOR_ALLOC freed 1007K, 45% free 26191K/47431K, paused 35ms
    10-14 13:44:09.160: INFO/dalvikvm-heap(31533): Grow heap (frag case) to 29.334MB for 3850256-byte allocation
    10-14 13:44:09.200: DEBUG/dalvikvm(31533): GC_CONCURRENT freed 0K, 37% free 29951K/47431K, paused 2ms+4ms
    10-14 13:44:11.970: DEBUG/dalvikvm(31533): GC_FOR_ALLOC freed 1878K, 38% free 29784K/47431K, paused 37ms
    10-14 13:44:12.410: DEBUG/dalvikvm(31533): GC_FOR_ALLOC freed 62K, 36% free 30441K/47431K, paused 32ms
    10-14 13:44:12.440: DEBUG/dalvikvm(31533): GC_FOR_ALLOC freed <1K, 32% free 32325K/47431K, paused 32ms
    10-14 13:44:12.440: INFO/dalvikvm-heap(31533): Forcing collection of SoftReferences for 3850256-byte allocation
    10-14 13:44:12.480: DEBUG/dalvikvm(31533): GC_BEFORE_OOM freed 124K, 33% free 32200K/47431K, paused 37ms
    10-14 13:44:12.480: ERROR/dalvikvm-heap(31533): Out of memory on a 3850256-byte allocation.

对于包含这么多日志记录,我深表歉意,我希望它是相关的。我读它的方式是系统不断重新调整堆大小,直到最终达到堆最大值。然后,我们请求一个特别大的分配失败。显然有足够多的可用内存(大约 15 兆)。这是否意味着堆在内部是 fragment 化的,并且没有足够大的连续内存段来处理我们的分配?如果是这种情况,我该怎么办?如果不是,那又是什么呢?

提前致谢。

最佳答案

奇怪的行为是因为位图是在 native 堆上分配的,而不是在垃圾收集上,但 android 只能跟踪垃圾收集堆上的对象。从 Android 2.2(或者可能是 2.3)开始,这已经发生了变化,如果您进行堆转储,分配的位图也可见。

回到问题,你的问题很可能是你手动加载的位图没有被适本地释放。一个典型的问题是某些回调仍然设置或 View 仍在引用位图。 另一个常见问题是,如果您手动加载大位图(而不是作为资源),您将需要在不再需要时对它们调用 recycle(),这将从 native 内存中释放位图,因此垃圾收集器将能够按应有的方式工作。 (GC 只看到 GC 堆上的对象,并不知​​道要释放哪个对象来释放 native 堆的内存,实际上甚至都不关心它。)

我身边一直有这个小宝贝:

public static void stripImageView(ImageView view) {
    if ( view.getDrawable() instanceof BitmapDrawable ) {
        ((BitmapDrawable)view.getDrawable()).getBitmap().recycle();
    }
    view.getDrawable().setCallback(null);
    view.setImageDrawable(null);
    view.getResources().flushLayoutCache();
    view.destroyDrawingCache();
}

关于android - 尽管可用内存可用,但 OutOfMemory 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7774723/

相关文章:

c# - UIElement 屏幕截图 UWP - C#

启动浏览器时黑莓 9800 模拟器崩溃

android - 如何以编程方式调用 ViewPager 的下一页?

java - 调整大小后的图像尺寸大于原始图像

android - TextView 在 ListView 的 ScrollView 内不可点击?

c++ - 位图到mat/2d数组

java - 单线程 Java 应用程序启动超过 70 个线程

java - servlet 如何处理比可用 RAM 更多的字节?

android - 放置自动完成 fragment 清除按钮设置可见性消失

android - Android-以编程方式更改EditText选择颜色