我开发了一个应用程序,它在启动时会解析一些相当大量的 JSON,这会导致堆增长接近其极限。稍后,该应用程序正在加载几个位图。在 Honeycomb 及以上设备上,似乎使用相同的内存区域进行位图分配以及 Java 对象分配,这不会导致任何问题,因为那时 JSON 解析所需的内存已被释放。但是在预蜂窝设备上,它会导致 OutOfMemoryErrors
由于堆大小永远不会下降,dalvik 似乎无法增加为外部分配(例如位图)保留的内存。
这是崩溃的一个示例日志输出
GC_EXTERNAL_ALLOC freed 601K, 81% free 5504K/27591K, external 4809K/5561K, paused 58ms
586224-byte external allocation too large for this process.
如您所见,堆上有大量可用内存,但用于外部分配的内存不多。
有没有办法可以强制 dalvik 进行碎片整理和缩小堆?或者我可以强制位图分配发生在堆上,而不是为外部分配保留的内存?或者还有其他方法可以解决我错过的这个问题吗?
** 更新 **
这是更多日志输出(特定设备不记录 dalvik-heap 消息):
在解析 JSON 时启动时,dalvik 堆会增长:
GC_CONCURRENT freed 800K, 19% free 12717K/15687K, external 2637K/2773K, paused 2ms+5ms
GC_CONCURRENT freed 871K, 19% free 13857K/16903K, external 2637K/2773K, paused 2ms+5ms
GC_CONCURRENT freed 1106K, 19% free 14766K/18055K, external 2637K/2773K, paused 3ms+5ms
GC_CONCURRENT freed 818K, 16% free 15946K/18951K, external 2637K/2773K, paused 3ms+6ms
GC_CONCURRENT freed 825K, 15% free 17151K/20167K, external 2637K/2773K, paused 2ms+6ms
GC_CONCURRENT freed 830K, 15% free 18356K/21383K, external 2637K/2773K, paused 2ms+5ms
GC_CONCURRENT freed 814K, 14% free 19519K/22535K, external 2637K/2773K, paused 2ms+6ms
GC_CONCURRENT freed 823K, 13% free 20720K/23751K, external 2637K/2773K, paused 2ms+5ms
GC_CONCURRENT freed 814K, 13% free 21873K/24903K, external 2637K/2773K, paused 3ms+6ms
GC_CONCURRENT freed 813K, 12% free 23016K/26055K, external 2637K/2773K, paused 2ms+5ms
GC_CONCURRENT freed 1771K, 15% free 23205K/27207K, external 2637K/2773K, paused 2ms+5ms
完成后,大部分堆再次成功释放:
GC_EXPLICIT freed 19207K, 83% free 4735K/27207K, external 2736K/2773K, paused 140ms
此时我有 20 MB 的可用 Dalvik 堆空间,稍后开始分配位图:
GC_EXTERNAL_ALLOC freed 254K, 83% free 4814K/27207K, external 2771K/2773K, paused 47ms
GC_EXTERNAL_ALLOC freed 721K, 83% free 4880K/27207K, external 3881K/4131K, paused 50ms
GC_EXTERNAL_ALLOC freed 235K, 83% free 4870K/27207K, external 5398K/5561K, paused 62ms
总设备限制似乎是 32 MB,dalvik 堆占用了其中的 27 MB,并且永远不会下降,所以我用完了外部内存空间来分配位图。