【问题标题】:Bitmap, Bitmap.recycle(), WeakReferences, and Garbage CollectionBitmap、Bitmap.recycle()、WeakReferences 和垃圾回收
【发布时间】:2023-03-19 11:11:01
【问题描述】:

在 Android 上 AFAIK,建议将 Bitmap 对象引用为 WeakReferences 以避免内存泄漏。当不再保留位图对象的硬引用时,垃圾收集器将自动收集它。

现在,如果我理解正确,必须始终调用 Bitmap.recycle() 方法来释放位图。我认为这是因为 Bitmap 对象具有特殊的内存管理。

对吗?

如果是这样,那么在使用 Wea​​kReferences 时,肯定会发生内存泄漏,因为在释放 WeakReferences 时永远不会调用 Bitmap.recycle()。或者,不知何故,WeakReferences 是否足以避免内存泄漏?

谢谢

【问题讨论】:

    标签: android memory-leaks garbage-collection bitmap weak-references


    【解决方案1】:

    Bitmap.recycle 不是必需被调用的,因为垃圾收集器最终会自行清理位图(只要没有引用)。 Android 中的位图是在本机内存中创建的,而不是在 VM 堆上,因此 VM 堆上的实际位图对象非常小,因为它不包含任何实际的位图数据。 (编辑:Android 3.0+ 不再是这种情况) 位图的实际大小仍将计入您的堆使用量,以用于 GC 并确保您的应用程序不会使用太多内存.

    但是,GC 在位图方面似乎有点喜怒无常。如果您只是删除所有硬引用,它有时(在我的情况下)会在位图上挂起一段时间,这可能是因为位图对象的分配/计数方式很奇怪。 Bitmap.recycle 似乎有助于让 GC 更快地收集该对象。

    无论哪种方式,只要您不意外保留硬引用,您就不会泄漏内存。但是,如果您尝试一次分配太多位图或未调用recycle 就分配了太大位图,您可能会遇到OutOfMemoryErrors

    编辑:需要注意的是,从 Android 3.0 开始,位图不再分配在本机内存中。它们像任何其他 Java 对象一样分配在 VM 堆上。但是,我所说的不需要调用回收仍然适用。

    【讨论】:

    • 清除解释。非常感谢!
    • 我以大约 20 秒的间隔加载图像。我调用 recycle() 但 Debug.getNativeHeapAllocatedSize() 表明本机内存分配不断增长,直到 OutOfMemoryError
    • 这对于 android 3 上,您不必调用 recycle,但不得将任何对位图的引用保留在您的活动范围之外。
    • @Kevin: This 2011 Google I/O talk by Android engineer Patrick Dubroy disagrees. 是的,在 3.0 之前,Bitmaps 为本地堆上的像素数据分配了内存(我在原始帖子中提到过),Bitmap 的真实大小仍然是计入您的 VM 堆使用量。但是,它们仍然可以并且将被垃圾收集(最终,假设您没有持有硬引用),此时它们的终结器将运行并调用一个本机方法,该方法frees 本机堆上的内存。
    • 现在,这并不意味着调用 recycle()since it seems to take a few passes 让 GC 决定收集 3.0 之前的位图并调用它们的终结器不是一个好主意,如果你也分配在 GC 正确释放未使用的位图之前,如果位图太多或太大,您可能会遇到 OutOfMemoryErrors。但是,我对原始问题的回答(您 必须 调用 recycle 否则会泄漏内存)仍然准确,因为 3.0 之前的位图 最终 甚至会被 GC如果你不调用回收站。
    猜你喜欢
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 2011-08-01
    • 2012-02-19
    • 2015-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多