This post is the result of providing solution for the ISSUE 'bitmap size exceeds VM budget' if Activity is restarted' filed at http://code.google.com.... click here ..... .

According to Andreas(who filed this bug), he tried to create and discard the image in the 'onCreate' method of app's Activity and if the Activity is restarted (because of the orientation changes or anything else check it here...)

Andreas's code is below, here he is creating 10 bitmaps...



Now, run the app but it blasts....


The reason of this is... allocation of the memory for PNG Image file(size 262.1 KB) that is converted to Bitmap is more frequently rather than the freed memory done by the DalvikVM's default GC routine, so before the GC do something the app has already gone.... :-(

This type of problem always comes when we play with Images in Garbage Collected environment like JVM (J2ME apps) and in this case Android app.

To handle this issue basic approach is make the recourses or objects 'null' and call 'System.gc()', Let's use this approach in this scenario...for that remove the final keyword from the 'InputStream is' and remaining as follows...

And it works fine, check it  below...


WE THINK it is GOOD!
But check my another approach below....


And the output of this is below...

Without GC calls it is working like a charm!!!
Yes, Android provides an api 'recycle()' for bitmap object. Let's see how does this api works...
________________________
Implementation of 'recycle'...

 public void recycle() {
        if (!mRecycled) {
            nativeRecycle(mNativeBitmap);
            mNinePatchChunk = null;
            mRecycled = true;
        }
    }

________________________
This method do a JNI call to a native api 'nativeRecycle'. 'nativeRecycle' is mapped to call another native method called 'Bitmap_recycle'.

{   "nativeRecycle",            "(I)V", (void*)Bitmap_recycle }

________________________
Implementation of the Bitmap_recycle...

static void Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {
    bitmap->setPixels(NULL, NULL);
}

________________________
Here the method 'setPixels' is called to do the hardwork....

void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
    this->freePixels();
    fPixels = p;
    SkRefCnt_SafeAssign(fColorTable, ctable);

    SkDEBUGCODE(this->validate();)
}
_________________________
Implementation 'freePixels' is below ...

void SkBitmap::freePixels() {
    // if we're gonna free the pixels, we certainly need to free the mipmap
    this->freeMipMap();

    if (fColorTable) {
        fColorTable->unref();
        fColorTable = NULL;
    }

    if (NULL != fPixelRef) {
        if (fPixelLockCount > 0) {
            fPixelRef->unlockPixels();
        }
        fPixelRef->unref();
        fPixelRef = NULL;
        fPixelRefOffset = 0;
    }
    fPixelLockCount = 0;
    fPixels = NULL;
}

and implementation of 'freeMipMap'...

void SkBitmap::freeMipMap() {
    if (fMipMap) {
        fMipMap->unref();
        fMipMap = NULL;
    }
}
_______________________

If your see above, in the 'freePixels' method it free the colortable, unlock the the pixel address for an existing bitmap then free the memory.

Conclusion: For Android specific we should use the 'recycle' method rather than 'gc', because 'recycle' will free the memory at the same time, but calling 'gc' doesn't guaranty to run and free the memory for same time(if it is not too critical, we should not call gc in our code) and results can very every time.
One more thing using 'recycle' is faster than the 'gc' and it improves the performance.

Update: "If we don't call recycle on the bitmap then it is GC's responsibility to free that, but in actually the timing for automatically call of GC to do this is uncertain and that make things worst. It is not bitmap's or any other object's responsibility to say hey i am done now they call or trigger GC. in other words it is not a bitmap or any other object's bug but...we can say that it is a GC optimization algorithm's bug while CPU is fully in use(that for loop) and missed the right timing ... and that is too late for that app. so as a partial responsibility we should call recycle or gc in our code, in that case recycle is best to use while GC comes with side effects."

Inputs are welcomed...

Happy Coding...
20

View comments

  1. what if it happened when i=0 at bitmap=bitmap(is) ?

    ReplyDelete
  2. Thanks a lot, really helped to explain what is going on here.

    ReplyDelete
  3. Is there a way to see the number of bytes currently allocated to bitmaps through DDMS or some other tool? I've been looking but can't figure it out.

    ReplyDelete
  4. Thanks a lot, it took me 3 days to solve this issue before reading your post.

    ReplyDelete
  5. not able to solve problem even after bitmap.recycle(), =null and is=null pls suggest something else...

    ReplyDelete
  6. Not working...createBimap fails after navigations to some screens...

    ReplyDelete
  7. Calling System.gc() manually is a very, very bad practice denoting a not mature Java VM implementation. All modern VMs will not make you utilize GC manually at all. I am really disappointed that Android's Dalvik VM suffers from this kind of desease. Only time could be cure for it, so we have to wait until Dalvik VMs creators will fix all this shit. But as practice shows this happens pretty rarely as mobile development always sucks.

    // As always, have a nice day, folks.

    ReplyDelete
  8. hello there,
    I have tried the above method , but when I try to save bitmaps some errors like " java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics" arose..

    I am trying to insert bitmaps to an array list using another variable(bitmap) along with recycle the current bitmap and then retrieving it in the last

    ReplyDelete
  9. I don't think System.gc helps because it collect Dalvic VM heap but bitmaps are in native memory.

    Probably you had no Error calling gc while it freed some memory from heap that is why overall memory (heap + bitmap native) was inside the limit

    ReplyDelete
  10. rahul p.m: I have the same problem. What is the solution?

    ReplyDelete
  11. hey i use ur sample code application,but it again show the same problem,it show is.close();
    wts the problem,pls give a better solutions to me as soon as possible,My Id:arun.saga@yahoo.in

    ReplyDelete
  12. Hey... Thank to you all for visiting this page...i was just busy in the things so there were no comments on your queries...!

    Please provide me the code block so i can help you better!

    -Sandy

    ReplyDelete
  13. HI, this is mayank here i am facing same problem here, with memory leaks, i tried everything from system.gc(),even making activity object null, but still ouccuring the same error, yeah it comes later about 15-20 mins in my app. Is it happening because of that, i am assinging bitmap from the resources.??? not using InputStream... please help me....

    ReplyDelete
  14. Sir thank you so much! Your advice really helped me put things into perspective!

    ReplyDelete
  15. Your article helped me complete my project without the OutOfMemory errors. Thank you!

    -Trung

    ReplyDelete
  16. First of all nice post
    I am facing the same problem in different scenario i.e,
    I had an activity with six button on click of each button I am starting six activity's respectively in that I am trying to set different xml files by considering the state of static boolean variable and changing the xml file.

    How to resolve this issue.
    Thanks in adavance

    ReplyDelete
  17. I am creating an app to display the US presidents but because I have so many images, my App is extremely slow at loading/touch feedback. Also if I have more than 10 images my app FC. What is the best way to modify to ensure it doesn't FC and the feedback stays normal?

    ReplyDelete
Extend your limits!
Things are changing now...Hey it's mobile world!
What is LIFE?
What is LIFE?
2
Visualize Your Business Network
Which mobile platform will be most important in 2011?
How to... if you want to create and destroy the Bitmaps too frequently...
20
oops-application-that-do-something-not
oops-application-that-do-something-not
Android EasyRoot! Explained...
A thought on mobile security threat
A thought on mobile security threat
1
Linux - Ubuntu : Sudo Power made easy
1
A peaceful day with sip of Bangalore Android Group Meetup
A peaceful day with sip of Bangalore Android Group Meetup
2
Mobility & Android (Mobile Application development)
USB Modem installation in Linux for dummies
12
My Jammu & kashmir tour...
Two powerful blasts of excitement – real story!!!
Two powerful blasts of excitement – real story!!!
2
Ok... i am back... after long time!!!
Ok... i am back... after long time!!!
Review : Opera mini on iPhone OS 4.0 (3GS)
What is new in iPhone 4.0 OS....!
1
The Magic behind operator/cell tower/BTS based location tracking... !
11
Cool : An advanced auto in bangalore.... :-)
18 Mobile Frameworks and Development Tools for Creating iPhone Apps
18 Mobile Frameworks and Development Tools for Creating iPhone Apps
OUTPUT OF : Hands on - Banaglore Android Group @ 3-April-2010 : 11 AM IST
7
Hands on : Banaglore Android Group @ 3-April-2010 : 11 AM IST
Hands on : Banaglore Android Group @ 3-April-2010 : 11 AM IST
Photos of Mobile Developer Conference E E 2010 ...
Nice coverage on Mobile Dev Conf E E...
Attended Tech days plus 2010...review
This friday (26 March 2010) ....i am attanding Tech days plus 2010....
iPhone application Link4's review...
My first post... :-)
My first post... :-)
Blog Archive
About Me
About Me
My Photo
http://www.linkedin.com/in/sandeepchoudhary If someone asks: What is you strength/skill? my simplest answer is: I can do everything that is possible(done by any guy around the globe) and i will do my best R&D if it is new for the mankind ...! Mobile no @ "+91 8527323616"
Loading
Dynamic Views theme. Powered by Blogger. Report Abuse.