BitmapFactory OOM driving me nuts?

Bitmap data is not allocated in the VM heap. There is a reference to it in the VM heap (which is small), but the actual data is allocated in the Native heap by the underlying Skia graphics library.

Bitmap data is not allocated in the VM heap. There is a reference to it in the VM heap (which is small), but the actual data is allocated in the Native heap by the underlying Skia graphics library. Unfortunately, while the definition of BitmapFactory.decode...() says that it returns null if the image data could not be decoded, the Skia implementation (or rather the JNI glue between the Java code and Skia) logs the message you’re seeing ("VM won't let us allocate xxxx bytes") and then throws an OutOfMemory exception with the misleading message "bitmap size exceeds VM budget".

The issue is not in the VM heap but is rather in the Native heap. The Natïve heap is shared between running applications, so the amount of free space depends on what other applications are running and their bitmap usage. But, given that BitmapFactory will not return, you need a way to figure out if the call is going to succeed before you make it.

There are routines to monitor the size of the Native heap (see the Debug class getNative methods). However, I have found that getNativeHeapFreeSize() and getNativeHeapSize() are not reliable. So in one of my applications that dynamically creates a large number of bitmaps I do the following.

The Native heap size varies by platform. So at startup, we check the maximum allowed VM heap size to determine the maximum allowed Native heap size. The magic numbers were determined by testing on 2.1 and 2.2, and may be different on other API levels.

Long mMaxVmHeap = Runtime.getRuntime().maxMemory()/1024; long mMaxNativeHeap = 16*1024; if (mMaxVmHeap == 16*1024) mMaxNativeHeap = 16*1024; else if (mMaxVmHeap == 24*1024) mMaxNativeHeap = 24*1024; else Log. W(TAG, "Unrecognized VM heap size = " + mMaxVmHeap); Then each time we need to call BitmapFactory we precede the call by a check of the form. Long sizeReqd = bitmapWidth * bitmapHeight * targetBpp / 8; long allocNativeHeap = Debug.

GetNativeHeapAllocatedSize(); if ((sizeReqd + allocNativeHeap + heapPad) >= mMaxNativeHeap) { // Do not call BitmapFactory… } Note that the heapPad is a magic number to allow for the fact that a) the reporting of Native heap size is "soft" and b) we want to leave some space in the Native heap for other applications. We are running with a 3*1024*1024 (ie 3Mbytes) pad currently.

A very interesting and practical approach. – CirrusFlyer May 26 '11 at 5:28 Interesting post. Do you got any proof/sources for this one?

: "The Natïve heap is shared between running applications, so the amount of free space depends on what other applications are running and their bitmap usage. " – mibollma Jul 8 '11 at 17:35 That was based on reading the Skia source, and in particular looking at how it handles bitmap.recycle(). But in retrospect, while I don't see any per-application references / handling in that code (which is what led me to that statement), I now think that's too strong / wrong.

The native heap will be allocated per-application, relying on the VM's normal per-process memory handling, and therefore the Skia code does not have to worry about per-application/process issues. – Torid Jul 8 '11 at 18:00 @Torid Where you do your If to check if there is enough space to create the bitmap. I don't see how you have the bitmaps width & height before you've decoded it?

Also what is targetBpp pls? – Blundell Jul 26 '11 at 20:29 You can use the inJustDecodeBounds option in developer.android.com/reference/android/graphics/… to get the bounds before you decode. – Torid Jul 29 '11 at 19:10.

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.

Although usually it doesn't make sense to catch an Error because usually they are thrown only by the vm but in this particular case the Error is thrown by the jni glue code thus it is very simple to handle cases where you could not load the image: just catch the OutOfMemoryError.

Bitmap scale take some amount of memory. Normally it takes some time regain the memory if we haven't use special flags with intents. I have a view that creates lot of images and android doesn't release memory sooner.

Then I used some flags with intents and it solved the issue. Try these options and see.. Intent intent = new Intent(getApplicationContext(), XXXX. Class); 1) intent.

SetFlags(Intent. FLAG_ACTIVITY_NO_HISTORY) 2) intent. SetFlags(Intent.

FLAG_ACTIVITY_CLEAR_TOP); 3) intent. SetFlags(Intent. FLAG_ACTIVITY_NO_HISTORY | Intent.

FLAG_ACTIVITY_CLEAR_TOP); 4) intent. SetFlags(Intent. FLAG_ACTIVITY_CLEAR_TOP | Intent.

FLAG_ACTIVITY_SINGLE_TOP).

Although this is a fairly high level answer, the problem for me turned out to be using hardware acceleration on all of my views. Most of my views have custom Bitmap manipulation, which I figured to be the source of the large native heap size, but in fact when disabling hardware acceleration the native heap usage was cut down by a factor of 4. It seems as though hardware acceleration will do all kinds of caching on your views, creating bitmaps of its own, and since all bitmaps share the native heap, the allocation size can grow pretty dramatically.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions