【问题标题】:Figuring out where bitmap was allocated at?弄清楚位图的分配位置?
【发布时间】:2023-03-05 00:17:02
【问题描述】:

我有一个应用程序在线程中获取位图,然后将位图放入全局内存缓存中。在 2.2 模拟器上,加载足够的位图(它们在列表视图中)后,我得到了一个可重现的内存不足错误:

FATAL EXCEPTION: pool-1-thread-1
  java.lang.OutOfMemoryError: bitmap size exceeds VM budget
  at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
  ...

堆看起来很稳定(3.3mb),我想知道我是否看不到内存量的增长,因为我认为在 2.2 操作系统中,位图内存是单独存储的?我一直在做 hprof 转储并在 MAT 中查看它们,我的对象计数看起来符合预期。

在 ICS 手机上运行应用程序不会出现同样的问题(但是,可能只是内存更多等)。我认为在后来的操作系统中,他们将位图内存作为堆的一部分?

在任何一种情况下,有没有办法查看我的应用程序分配了哪些位图实例?我认为 hprof 转储仅显示系统范围内的总计数。但是我看不到它们是从哪里分配的。

我正在使用:

android.support.v4.util.LruCache<String, Bitmap> 

作为 memcache - 在条目被驱逐后,位图数据似乎没有被清理(我将缓存设置为 5mb 上限)。我记得 Bitmap 上有类似 recycle() 的方法,也许它们没有被正确清理?

谢谢

【问题讨论】:

    标签: android


    【解决方案1】:

    堆看起来很稳定(3.3mb),不知是不是看不到数量 内存增长,因为我认为在 2.2 操作系统中,位图内存是 分开存放?我一直在做 hprof 转储并在 MAT 中查看它们, 并且我的对象计数看起来符合预期。

    正确,对于 2.x,您看不到位图使用 MAT 占用的内存(您可以从 ICS 设备进行转储并突然看到巨大的跳跃)。但是,可用的内存量是相同的(但取决于设备,通常在 16 MB 和 32 MB 之间)。解决方案是在内存中保留尽可能少的位图。如果它们只是缩略图大小,您可能会避免将它们保留在内存中,但通常您无法加载那么多。

    【讨论】:

      【解决方案2】:

      你是对的,更高版本将位图数据保留在本机堆中。但即便如此,这些数据仍然计入位图预算。为避免此错误,您必须调用回收!所以扩展 LruCache,覆盖entryRemoved 并在那里调用回收。 此外,我会根据设备内存对缓存进行限制。例如,您可以使用ActivityManager.getMemoryClass()

          ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
          int memoryClass = activityManager.getMemoryClass();
      

      memoryClass 包含以 MB 为单位的 dalvik 堆。例如,您可以使用该值的 1/5 作为缓存的限制。

      这可能还不足以避免 OOM 错误,因为位图内存仅在终结器中被释放。请务必阅读有关位图处理的official doc。如果一切都失败了,您仍然可以尝试在entryRemoved 中拨打System.gc() 看看是否有帮助。但正如 Ewoks 所指出的,这不仅是一种不好的做法,而且还可能导致 UI 线程停止一段时间,因此只能作为最后的手段。

      【讨论】:

      • 我同意除了手动调用 System.gc() 之外的所有内容,这被认为是不好的做法。每个 gc(由系统或代码调用)都会产生小的响应延迟(~15-20ms),这总是不利于 UI 响应..
      • 全票应得的 :) 希望你喜欢 Android 仙境.. :) 干杯
      • 在 entryRemoved 中调用回收可能是个问题。在stackoverflow.com/a/10747001/450580 中阅读更多信息。另一方面,在不回收而不是手动 GC 时,您可能会遇到 OOM 错误,所以我认为 GC 是这次无法避免的最后手段。
      猜你喜欢
      • 2012-03-28
      • 2014-10-16
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-26
      相关资源
      最近更新 更多