BitmapFactory OOM driving me nuts

Viewed 25259

I've been doing a lot of searching and I know a lot of other people are experiencing the same OOM memory problems with BitmapFactory. My app only shows a total memory available of 4MB using Runtime.getRuntime ().totalMemory(). If the limit is 16MB, then why doesn't the total memory grow to make room for the bitmap? Instead it throws an error.

I also don't understand that if I have 1.6MB of free memory according to Runtime.getRuntime().freeMemory() why do I get an error saying "VM won't let us allocate 614400 bytes"? Seems to me I have plenty available memory.

My app is complete except for this problem, which goes away when I reboot the phone so that my app is the only thing running. I'm using an HTC Hero for device testing (Android 1.5).

At this point I'm thinking the only way around this is to somehow avoid using BitmapFactory.

Anyone have any ideas on this or an explanation as to why VM won't allocate 614KB when there's 1.6MB of free memory?

5 Answers

1.6 MB of memory seems like a lot but it could be the case that the memory is so badly fragmented that it can't allocate such big block of memory in one go (still this does sound very strange).

One common cause of OOM while using image resources is when one is decompressing JPG, PNG, GIF images with really high resolutions. You need to bear in mind that all these formats are pretty well compressed and take up very little space but once you load the images to the phone, the memory they're going to use is something like width * height * 4 bytes. Also, when decompression kicks in, a few other auxiliary data structures need to be loaded for the decoding step.

It seems like the issues given in Torid's answer have been resolved in the more recent versions of Android.

However, if you are using an image cache (a specialized one or even just a regular HashMap), it is pretty easy to get this error by creating a memory leak.

In my experience, if you inadvertently hold on to your Bitmap references and create a memory leak, OP's error (an referring to the BitmapFactory and native methods) is the one that will crash your app (up to ICS - 14 and +?)

To avoid this, make your you "let go" of your Bitmaps. This means using SoftReferences in the final tier of your cache, so that Bitmaps can get garbage collected out of it. This should work, but if you are still getting crashes, you can try to explicitly mark certain Bitmaps for collection by using bitmap.recycle(), just remember to never return a bitmap for use in your app if bitmap.isRecycled().

As an aside, LinkedHashMaps are a great tool for easily implementing pretty good cache structures, especially if you combine hard and soft references like in this example (starting line 308)... but using hard references is also how you can get yourself into memory leak situations if you mess up.

Related