views:

79

answers:

2

I'm having some trouble understanding why this code

public class BitmapAllocTest extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);       
        byte[] b = new byte[20 * 1000 * 1000];
        b = null;
        Bitmap.createBitmap(2500, 2000, Bitmap.Config.ARGB_8888);
    }
}

throws an OutOfMemory exception on a device with a 24mb heap limit. If I comment out either of the allocations it runs fine. I was under the impression that the java vm would try to garbage collect before throwing OutOfMemory exceptions.

I suspect it having to do with android allocating the bitmaps on the native heap.

A: 
I was under the impression that the java vm would try to garbage collect before throwing OutOfMemory exceptions.

You have to trigger the GC by yourself and retry. I had to do that recently and couldn't figure out another way to do that.

WarrenFaith
I tried your suggestion calling System.gc() before the bitmap allocation, also tried catching the error, calling gc() and then trying to allocate the bitmap again. I still get the OOM error though. :(
Viktor
can you show me how you call and retry it?
WarrenFaith
byte[] b = new byte[20 * 1000 * 1000];b = null;System.gc();try {Bitmap.createBitmap(2500, 2000, Bitmap.Config.ARGB_8888);} catch(OutOfMemoryError e) {System.gc();Bitmap.createBitmap(2500, 2000, Bitmap.Config.ARGB_8888);}
Viktor
hm... well I have multiple bitmaps and recycled each one before calling the GC, which is not possible in your case...I guess nulling the array isn't enough for the GC to grep it. only a guess
WarrenFaith
A: 

I posted this on the issue tracker and got this answer:

There are a couple of things going on.

The VM on older devices uses conservative collection. Most (but not all) devices running >= 2.0 will use type-precise GC, but none of them yet have live-precise GC.

What this means is, the fact that you set "b = null" doesn't guarantee that all copies of that reference are gone -- a copy might still be sitting in a register somewhere, and without liveness detection the GC can't know that it will never be used again. It's also perfectly legal for the compiler to discard the "b = null" assignment since you never look at "b" again.

Bitmap pixel data uses the magical "external allocation" mechanism rather than the usual heap allocator. Sometimes you get unpleasant interactions.

We're working on fixing all of these issues.

Link: http://code.google.com/p/android/issues/detail?id=10821

Viktor