当我尝试加载大小接近应用程序堆最大大小的图像时,我的应用程序崩溃了。第一次加载图像很好,然后删除对Bitmap对象的引用,并在调用mBitmap.recycle()// nativeRecycle的位置将其终结。显然内存使用减少,但是当我尝试再次加载图像时,出现OutOfMemory崩溃。
有趣的是,如果我只是在删除引用的同一类中调用回收站,则似乎内存已释放,并且可以再次加载图像。因此,基本上,如果直接调用mBitmap.recycle()而不是将mBitmap.recycle()放入引用位图的对象的终结处理中,我得到的结果将有所不同。知道为什么会这样吗?
最佳答案
如果您接近使用堆的最大大小,那么您可能会很幸运(或很不幸)。直接调用recycle()与从终结器调用它可能会改变GC的时间和行为,从而使您看到差异。
您确定在尝试重新分配位图之前已调用终结器(和recycle())吗?终结器不可靠,可以无限期推迟。即使您当前在测试期间看到终结器在重新分配之前被调用,也无法保证会一直发生(特别是对于不同的堆状态或Dalvik的将来/不同版本)。
如果可以,请尝试从终结器外部调用recycle()。如果您知道何时完成,只需调用该方法即可;否则,请考虑使用ReferenceQueue(https://stackoverflow.com/a/10879076/150001)。
自从我看Dalvik以来已经有一段时间了,但是我似乎还记得,位图缓冲区可能需要花费几个GC周期才能清理,因为VM需要确保没有任何本机代码将剩余的指针插入其中。因此,缓冲区可能无法完全按照您的预期释放。
尽管很有可能使用mmap()分配了较大的缓冲区,并且不会助长碎片(同样取决于Dalvik的当前版本),但也会出现堆碎片导致问题的可能性。