3

So I'm having an infamous oom error caused by large bitmaps. But I've managed to fix most of the issues. The only issue remaining happens when I click back and close the app and then launch the app right after. Then the app will crash giving me a oom (out of memory) error. This wont happen if I click home.

Why is this happening? My guess is that the GC hasn't finished clearing up and now I start it up while the old data is still lying around. And of course it isn't a new app so the old launch and the new launch goes under the same app memory limitation.

Any inputs on this issue and possible solutions would be great.

What I've tryed:

On all download of bitmaps I've used:

BitmapFactory.Options op = new Options();
op.inPurgeable = true;
bmImg = BitmapFactory.decodeStream(is,null,op);

Making the images smaller in dimensions width x height (the size in kb is approximately the same). <-- This solves the problem so I have a fall-back solution unless there is someone out there with a super solution :)

Snippet of error log:

06-25 04:29:28.917: E/AndroidRuntime(8819): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:715)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.content.res.Resources.loadDrawable(Resources.java:1713)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.widget.ImageView.<init>(ImageView.java:122)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.widget.ImageView.<init>(ImageView.java:112)
06-25 04:29:28.917: E/AndroidRuntime(8819):     ... 23 more

Edit: So two things fix this issue for me.

  1. Clearing my database and setting the large image to null in ondestroy() of my main activity.
  2. Making the large images smaller.

But this just raises the same fundamental question, if onDestroy() is called, why isn't my activity closed properly before a new one is opened? Also I see my activity keep on running long after it is closed. Could this be related to the issue? How do I track down the cause of this?

Edit2: The culprint seems to be my LruCache. I use a static lrucache which isn't cleared in ondestroy(). When the app is restarted all the images in the lrucache is still present which causes problems. I'm still wondering why this only is a problem on restart? Shouldn't this also be a problem when I return to my main activity just before I close it?

Warpzit
  • 27,966
  • 19
  • 103
  • 155
  • This may be big file size on Bitmap decode,so u can try this post for bitmap big size file decoding solution: http://stackoverflow.com/questions/477572/android-strange-out-of-memory-issue-while-loading-an-image-to-a-bitmap-object/823966#823966 Welcome! – Dinesh Jun 18 '12 at 12:33

3 Answers3

2

I had the same problem which was solved by force closing the process. This can be done by overriding onDestroy(). Use this:

@Override
public void onDestroy(){
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> pids = am.getRunningAppProcesses();
    for (int i = 0; i < pids.size(); i++) {
        ActivityManager.RunningAppProcessInfo info = pids.get(i);
        if (info.processName.equalsIgnoreCase(context.getPackageName())) {
            android.os.Process.killProcess(info.pid);
        }
    }
    super.onDestroy();
}
Behzad Momahed Heravi
  • 1,383
  • 1
  • 12
  • 17
  • This would probably work, but I think I'll try to find the reference that makes my app not close properly. – Warpzit Jun 19 '12 at 06:52
  • After some reading (commonsware among others) I wont go in this direction. This might cause all kind of other troubles. – Warpzit Jun 19 '12 at 07:12
  • I understand your concerns, but I haven't found a better solusion yet. – Behzad Momahed Heravi Jun 19 '12 at 10:08
  • I prefer the "Android" way and thereby letting the system close my apps. What I found out is that static variables isn't cleared when your app is closed. So for my problem I'll make sure to set these varialbes to null in ondestroy() – Warpzit Jun 19 '12 at 10:49
1

Hey please check my answer on the same issue: bitmap size exceeds Vm budget error android

And also always try to use maximum options while dealing with bitmaps like this:

        final Options options = new Options();
        options.outHeight = (int) scaleHeight; // new smaller height
        options.outWidth = (int) scaleWidth;   // new smaller width
        options.inScaled = true;
        options.inPurgeable = true;

        // to scale the image to 1/8
        options.inSampleSize = 8;
        bitmap = BitmapFactory.decodeFile(imagePath, options);

This might solve your problem.

Community
  • 1
  • 1
Shrikant Ballal
  • 7,067
  • 7
  • 41
  • 61
  • I already use inPurgeable. inSampleSize will reduce quality, this is not an option. I need the image in the size it comes in. – Warpzit Jun 18 '12 at 12:45
  • If the size of your image is very large like 2 to 3 mb, then loading the images will cause this error. What is the size of image? Check if your code has any memory leak, this might also be the problem. – Shrikant Ballal Jun 18 '12 at 12:48
  • mdpi is 900 x 900 px and ~93kb, hdpi scalled up – Warpzit Jun 18 '12 at 12:49
  • if the image is not very large, then check for WeakReference. And when you deal with bitmaps, always call its recycle() method as soon as you are done with bitmaps. – Shrikant Ballal Jun 18 '12 at 12:51
  • I use a lrucache for all images download from web etc. The problem happens on restart of the app when it needs to create a large wheel image. – Warpzit Jun 18 '12 at 12:55
  • Use MAT that is a plugin for eclipse. I think you surely has a memory leak. Because, if your app is exiting, your objects should get collected by GC, if some objects are not getting collected by GC, then that means the objects are still holding references. Please check if such thing is happening. – Shrikant Ballal Jun 18 '12 at 13:06
  • I think you might be right. I've tried using MAT but without great success. Will try to see if I can locate the leak. – Warpzit Jun 18 '12 at 13:18
  • Sure. And also, if you get the answer, then don't forget to update this post. All the best. – Shrikant Ballal Jun 18 '12 at 13:24
0

The culprint seems to be my LruCache. I use a static lrucache which isn't cleared in ondestroy(). When the app is restarted all the images in the lrucache is still present which causes problems. I'm still wondering why this only is a problem on restart? Shouldn't this also be a problem when I return to my main activity just before I close it?

Nevertheless my temp/permanent fix of this issue is to clean all static references in ondestroy(), but also to use images of smaller size. This seems to solve all my problems as I'm also not able to find any memory leaks.

Warpzit
  • 27,966
  • 19
  • 103
  • 155