我正在测试安卓3.1系统,使用了大堆内存选项,大约有250M的可用内存。
我设置了以下代码,每当我在应用程序设置中点击“测试”按钮时运行:
float [][][]foo = new float[3][2048][2048];
Bitmap bm = Bitmap.createBitmap(2048, 2048, Bitmap.Config.ARGB_8888);
bm.recycle();
bm = null;
foo = null;
我有足够的内存可以多次点击按钮而没有问题。但是,如果我继续点击按钮,最终(少于20次点击)会出现OutOfMemory错误。[通常在android.graphics.Bitmap.nativeCreate(本机方法)中]除了我点击按钮时显示的一个小Toast之外,没有其他活动。这是由于内存碎片还是android位图代码和/或GC中的可怕错误?还是我做了一些愚蠢的事情?(请让它变得愚蠢...)是否有人有解决方法?因为上述情况相当代表了每次用户调用该代码时必须执行的操作,而且现在即使变量清除非常谨慎,也会在几次使用后死亡。(这已经让我困扰很长时间了!)[更新]
我确认这是一个内存碎片问题或gc bug,因为堆转储显示我空闲时仅使用5.6M(无泄漏),处理期间峰值约为26M。(此外,本机堆仍保持在4M以下。)同时,java堆的范围不断扩大到测试设备的280M限制,在此点处开始收到OutOfMemory异常。因此,我只在峰值时使用了可用堆的10%,但却出现了OutOfMemory。
[添加对System.gc()的调用不幸地修复了我给出的简单测试用例。我说不幸是因为(A)它不应该有任何影响,(B)因为我已经定期在我的真实代码中调用它,所以这意味着我的简单测试用例太简单了。]
有其他人遇到过这种情况吗?有什么解决方法?是否有一种优雅的方式来重新启动我的应用程序?
[更新]
以下版本可靠地导致OutOfMemory出现3至4次调用(按钮按下):
float [][][]foo = new float[3][2048][2048];
Bitmap bm = Bitmap.createBitmap(2048, 2048, Bitmap.Config.ARGB_8888);
int []bar = new int[3*2048*2048];
bm.recycle();
bm = null;
System.gc();
foo = null;
System.gc();
bar = null;
System.gc();
内存跟踪显示堆在每次调用时稳定增长,直到达到极限并死亡。如果我删除其中任何一个分配,它就会达到平衡并无限存活。只删除除最后一个gc()之外的所有操作会导致它稍微更快地死亡。
我认为这是一个碎片化问题,不是 gc 的 bug 本身。如果有人知道如何解决它,请告诉我。int[] 分配用于编写位图,因此我没有将其分配为二维数组的选项(这是 Android Bitmap 库的限制)。
System.gc();
调用正是解决此问题所需的,因为GC期望较小的对象。 - Ancantus