13

I've seen in a lot of samples, that developers call recycle() on bitmap, and then set it to null. Why is this necessary, doesn't the garbage collector take care of releasing the bitmap?

Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
bitmap.recycle();
bitmap = null;
aryaxt
  • 76,198
  • 92
  • 293
  • 442

4 Answers4

17

Join the club. It kind of does but not quite.

The thing is that in the pre-Honeycomb versions of Android the memory for bitmaps was (is) allocated from unmanaged memory, which creates all sorts of problems. It is still released but from the finalizer of the bitmap object implementation. Which means that it will take at least 2 passes of GC to collect it. Also if for whatever reason the finalizer fails to execute - you got the picture. Another thing is - it is really difficult to trace - DDMS does not see it and neither does MAT

For Android 3.0 this has been changed and bitmaps are implemented over managed byte arrays, but for the older phones...

Dallas
  • 1,045
  • 1
  • 8
  • 25
mfeingold
  • 7,094
  • 4
  • 37
  • 43
3

bitmap.recycle(); release the native heap that is used in bitmaps.And setting it to null is to assist the GC to quickly collect your reference.

Navin Ilavarasan
  • 1,271
  • 11
  • 15
  • 3
    @aryaxt: Note that while the finalizer will do a `recycle()` for you, calling it yourself releases the memory sooner, making it that much less likely you will run out of heap space. – CommonsWare Jan 25 '12 at 01:14
  • 1
    yes....one more thing to note....you need to be sure that the bitmap is no more used before you recycle...otherwise you would run into exceptions when trying to use a recycled bitmap. – Navin Ilavarasan Jan 25 '12 at 01:17
  • 4
    Also as of Android 3.0 bitmaps do not use the native heap anymore. – Romain Guy Jan 25 '12 at 02:08
1

From docs at http://developer.android.com/reference/android/graphics/Bitmap.html#recycle%28%29.


Free the native object associated with this bitmap, and clear the reference to the pixel data. This will not free the pixel data synchronously; it simply allows it to be garbage collected if there are no other references. The bitmap is marked as "dead", meaning it will throw an exception if getPixels() or setPixels() is called, and will draw nothing. This operation cannot be reversed, so it should only be called if you are sure there are no further uses for the bitmap. This is an advanced call, and normally need not be called, since the normal GC process will free up this memory when there are no more references to this bitmap.


So it doesn't seem to be necessary to call. The only time I've ever heard a need to manually set an object to null is if its a static variable (or some variable that won't go out of scope easily) and you want to force it out of memory. Maybe if you are continuously allocating bitmaps rapidly there may be a need to try and force garbage collection, but for the majority of cases it is probably not needed.

onit
  • 6,306
  • 3
  • 24
  • 31
  • 1
    All seems well as per the documentation,but there has been so many cases where the bitmap has caused OOM....so if you face this issue in your code a general way to fix it is to make sure that we set bitmap to null and call the gc from code...(yes i know this is not the optimal and it is not guranteed to gc)...but this has been a last resort to get some memory back....You can also try using SoftReferences for bitmap caching – Navin Ilavarasan Jan 25 '12 at 01:24
  • I've loaded hundreds of bitmaps into memory at once and haven't had a problem. The only way I can see this is a problem on modern phones is if you are memory leaking your bitmaps or you are rapidly allocating and throwing away bitmaps (much more than you can fit on your screen at once). – onit Jan 25 '12 at 01:32
  • http://code.google.com/p/android/issues/detail?id=11089 Check romain guys response.... – Navin Ilavarasan Jan 25 '12 at 02:03
  • His response does nothing to back your claim that you need to call recycle regularly. I could not even look at the code file posted, nor does the person mention any details about the emulator settings, such as device ram size. Romain guy's response actually seems to backs up what I said, that it would only be necessary if you were rapidly allocating and throwing away bitmaps. Again, I've never done it in any of my apps, and I've loaded up to hundreds of bitmaps (at least 300 around 100x100) at once and never had a problem. – onit Jan 25 '12 at 03:42
  • "so if you face this issue in your code a general way to fix it is to make sure that we set bitmap to null and call the gc from code" If you can check my comment I do say that if you run into memory issues...we need to then inform the GC to collect the bitmaps...as you need atleast 2-3 GC cycles to actually collect the native heap...a faster way would be to notify the GC that the native heap can be collected right away since my application would not be using it anymore... – Navin Ilavarasan Jan 25 '12 at 10:28
  • ...and in most of the cases we would not load 100's of bitmaps at once and keep it for the scope of the app(except in very specific scenarios)... – Navin Ilavarasan Jan 25 '12 at 10:28
0

This article from android development docs has a lot of information on this topic. While you're at it also check the article about caching if you'll be using multiple bitmaps.

hcpl
  • 17,382
  • 7
  • 72
  • 73