finalize方法中的位图回收无法正常工作

时间:2013-03-09 15:58:42

标签: java android bitmap heap finalize

当我尝试加载大小接近应用程序堆最大大小的映像时,我的应用程序崩溃了。我第一次加载图像是好的,然后我删除对Bitmap对象的引用及其finalize,我调用mBitmap.recycle()// nativeRecycle被调用。显然内存使用减少了,但是当我尝试再次加载图像时,我得到了OutOfMemory的崩溃。 有趣的是,如果我在同一个类中调用回收,我删除引用似乎释放了内存,我可以再次加载图像。因此,如果我直接调用mBitmap.recycle(),那么基本上我会得到不同的结果,而不是将mBitmap.recycle()放在引用Bitmap的对象的finalize中。知道为什么会这样吗?

1 个答案:

答案 0 :(得分:1)

如果你接近使用堆的最大大小,你可能会变得幸运(或不幸)。直接调用recycle()与从终结器调用它可能会改变GC的时间和行为,使您看到差异。

在尝试重新分配位图之前,您确定要调用终结器(和recycle())吗?终结器不可靠,可以无限期推迟。即使你现在看到在测试期间重新分配之前调用终结器,也不能保证这总是会发生(特别是对于不同的堆状态或未来/不同版本的Dalvik)。

如果可以的话,尽可能努力从终结者的外部调用recycle()。如果你知道什么时候完成,只需调用方法;否则请考虑使用ReferenceQueue(https://stackoverflow.com/a/10879076/150001)。

自从我查看Dalvik已经有一段时间了,但我似乎记得位图缓冲区可能需要几个GC周期才能被清理,因为VM需要确保没有本机代码有任何剩余的指针。因此,缓冲区可能无法在您预期的时间内准确释放。

堆碎片也有可能导致问题,尽管很有可能使用mmap()分配大缓冲区并且不会导致碎片(同样,取决于Dalvik的当前版本)。