现象:先在Java端分配一些大内存块,直到遇到OutOfMemoryError,然后全部释放。现在,奇怪的事情发生了:通过 BitmapFactory.decodeXXX(decodeResource, decodeFile, ...) 加载即使是小图片(例如宽度:200,高度:200)也会抛出 OutOfMemoryError!但是现在可以分配任何纯 Java 大对象(例如 new byte[2*1024*1024])!
验证:我写了一些简单的代码来验证问题,可以在这里下载,按“Alloc”按钮多次,你会得到一个OOF错误,然后按“Free All”,现在环境设置好了。现在你可以按“LoadBitmap”,你会发现它在大多数 Android 2.x 手机上都不起作用。(但在模拟器中它还可以,奇怪)
深入挖掘:我尝试深入研究一些 dalvik 代码以找出原因,并在 HeapSource.c 中的函数 externalAllocPossible 中找到一个可能的错误,该错误由dvmTrackExternalAllocation 调用,后者在 LogCat 中打印“xxx-byte external allocation too large for this process”消息.
在 externalAllocPossible 中,它简单地写道:
if (currentHeapSize + hs->externalBytesAllocated + n <=
heap->absoluteMaxSize)
{
return true;
}
return false;
这意味着一旦本机位图分配大小加上 currentHeapSize(不是实际分配的大小,如下所示,在这种情况下,它保持我们碰撞的堆的最大大小,然后将它们全部释放)超过限制,本机位图分配总是会失败,但是即使 91.3% Java 对象的内存已被释放(设置为 null 并触发 GC),Java 中的 currentHeapSize 似乎也不会减少!
还有其他人也遇到过这个问题吗?