I am testing on android 3.1, large heapsize option, about 250M of memory available.
I set the following code to be run whenever I hit a Test button in my app's prefs:
float [][][]foo = new float[3][2048][2048];
Bitmap bm = Bitmap.createBitmap(2048, 2048, Bitmap.Config.ARGB_8888);
bm.recycle();
bm = null;
foo = null;
I have plenty of memory for this -- I can hit the button a few times without problem.
But if I keep hitting the button, eventually (less than 20 hits) it dies with OutOfMemory. [Usually in android.graphics.Bitmap.nativeCreate(Native Method)]
Nothing else is going on -- I never have to leave the PreferencesActivity. There is a small Toast that is also displayed when I hit the button, so a tiny amount of other UI activity is going on.
Is this due to fragmentation, or just a horrible bug in the android Bitmap code and/or GC? Or am I just doing something stupid? (Please let it be something stupid...)
Does anybody have a workaround? Because the above is fairly representative of what my code has to do each time the user invokes it, and right now despite meticulous clearing of variables it dies after a few uses. (And this has been driving me nuts for a long time now!)
[Update]
I have confirmed it's a fragmentation issue or gc bug, as a heap dump shows I'm only using 5.6M when idle (no leaks) peaking at about 26M during processing. (Also, native heap stays below 4M.) While the java heap meanwhile grows in extent all the way to the 280M limit on my test device at which point I start getting OutOfMemory exceptions. So I am only using 10% of my available heap at peak, but getting OutOfMemory.
[Adding a call to System.gc() unfortunately fixes the simple test case I give above. I say unfortunate because (A) it shouldn't make a difference, and (B) because I already call it regularly in my real code so it means my simple test case above is too simple.]
Has anyone else run into this? Any workarounds? Is there a graceful way to restart my app?
[Update]
The following version reliably causes OutOfMemory in 3 to 4 invocations (presses of the button):
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();
Memory tracing shows the heap growing steadily each invocation until it hits the limit and dies. If I remove any one of the three allocations, it reaches equilibrium and survives indefinitely. Removing all but the last gc() causes it to die slightly sooner.
I would say this is a fragmentation issue, not a gc bug per se. If anybody knows how to fix it, let me know. The int[] allocation is for writing a Bitmap so I do not have the option of allocating it as a 2d array (limitation of the android Bitmap library).