Android:OutofMemoryError:位图大小超出 VM 预算,我看不到任何理由

标签 android gallery imageview out-of-memory ddms

我的库超过 600x800 像素 JPEG 时出现 OutOfMemory 异常。


环境

我一直在使用包含 600x800 像素左右的 JPG 图片的图库。

由于我的内容可能比图像更复杂一些,因此我将每个 View 设置为将 ImageView 与 JPG 包装在一起的 RelativeLayout。

为了“加速”用户体验,我有一个简单的 4 个插槽缓存,预取(在循环器中)大约 1 个图像左侧和 1 个图像右侧显示图像,并将它们保存在 4 个插槽 HashMap 中。

平台

我正在使用 256 RAM 和 128 堆大小的 AVD,屏幕为 600x800。 它也发生在 Entourage Edge 目标上,只是在设备上更难调试。


问题

我遇到了一个异常:

OutofMemoryError: bitmap size exceeds VM budget

在获取第五张图片时会发生这种情况。我已尝试更改图像缓存的大小,但还是一样。


奇怪的是:应该没有内存问题

为了确保堆限制离我需要的很远,我在开始时定义了一个 8MB 的虚拟数组,并没有对其进行引用,因此它会立即被调度。它是 Activity 线程的成员,定义如下

static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }    

结果是堆大小接近 11MB,并且全部空闲。 注意我在它开始崩溃后添加了这个技巧。它会降低 OutOfMemory 的频率。

现在,我正在使用 DDMS。就在崩溃前(崩溃后变化不大),DDMS 显示:

ID  Heap Size   Allocated   Free       %Used    #Objects
1   11.195 MB   2.428 MB    8.767 MB   21.69%   47,156  

在明细表中显示:

Type  Count  Total Size   Smallest   Largest   Median    Average
free  1,536  8.739MB      16B        7.750MB   24B       5.825KB

最大的 block 是 7.7MB。然而 LogCat 说:

ERROR/dalvikvm-heap(1923): 925200-byte external allocation too large for this process.

如果您介意中位数和平均值的关系,可以假设大多数可用 block 非常小。但是,有一个足够大的 block 用于位图,它是 7.7M。怎么还不够呢?

注意:我记录了一个堆跟踪。看分配的数据量,感觉分配不超过2M。它确实与 DDMS 的可用内存报告相符。


  • 会不会是我遇到了诸如堆 fragment 之类的问题?
  • 如何解决/解决问题?
  • 堆是否共享给所有线程?
  • 会不会是我对 DDMS 读数的解释有误,真的没有 900K block 可以分配?如果是这样,谁能告诉我在哪里可以看到?

非常感谢

梅曼

最佳答案

我认为你的情况没有什么特别之处。只是内存不够。内存中不能有多个 600x800 位图,它们会占用太多内存。您应该将它们保存到 SD 并按需加载到内存中。我认为这正是你所做的。

您应该注意的一件事:DDMS 显示 java 堆内存消耗。但也有未在 DDMS 中显示的 native 内存。据我所知,位图是在 native 内存中创建的。所以 DDMS 只是一个不好的工具来跟踪这些内存问题。您只需要确保释放内存,垃圾收集器会在您不再需要图像后收集它们。

垃圾收集器按自己的时间表工作。这就是为什么您应该在不再需要的位图上调用 Bitmap.recycle() 方法。此方法完全释放您用完的 native 内存。这样就不用依赖 GC 了,可以尽快释放最大的一 block 内存。

首先你应该确保你不会泄露位图。

这是一个不错的 post关于内存分配,它可以帮助您更深入地挖掘

关于Android:OutofMemoryError:位图大小超出 VM 预算,我看不到任何理由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3037027/

相关文章:

android - 反复设置recyclerview项目背景色

android - 如何通过 viewModels 实现?

jquery - 将全屏图库导航更改为项目符号导航

java - 如何将我的 Activity 背景设为白色?

android - firebase电话身份验证问题,不发送验证短信

android - 更新到 android studio 后用户无法登录

html - 带有图像的复杂网格

iphone - 如何制作 UIScrollView 图片库? (iPhone SDK)

java - 从 uri android 加载图像

ios - 如何将 ImageView 转换并放大为形状(swift3)