0

I have 3 image resources in my app. Loading and displaying any one of them in an ImageView goes smoothly. But when I remove the displayed ImageView from the layout, null it and add a new image, things get weird.

Either the process crashes completely (signal 11) when I try calling .recycle() on the old bitmap or I get an OutOfMemoryError in case I don't use recycle.

This only happens on API Levels below 8, so my guess is that bugs with GC on the native heap are causing it and these bugs were fixed on 2.2. However, since 2.1 is currently the most common version out there I need a workaround...

Again, there shouldn't be a lack of memory for the native heap. I hold only 1 image at a time and null the previous so the GC should be able to retrieve the heap space (like happens on 2.2).

I've created a very small sample app which can be downloaded from here: http://www.4shared.com/file/QqHrhJLR/BitmapRecycleTest.html

Any suggestions will be appreciated.

Roi
  • 83
  • 7

2 Answers2

1

I've taken a look. I get the signal 11 on a Nexus One running 2.2.1. The callstack is this:

I/DEBUG   (   56):          #00  pc 0000c584  /system/lib/libc.so
I/DEBUG   (   56):          #01  pc 0000cd2e  /system/lib/libc.so
I/DEBUG   (   56):          #02  pc 0002c5dc  /system/lib/libskia.so
I/DEBUG   (   56):          #03  pc 00068108  /system/lib/libskia.so
I/DEBUG   (   56):          #04  pc 00063a8c  /system/lib/libskia.so
I/DEBUG   (   56):          #05  pc 0004cefc  /system/lib/libandroid_runtime.so
I/DEBUG   (   56):          #06  pc 00016e34  /system/lib/libdvm.so
I/DEBUG   (   56):          #07  pc 000452c4  /system/lib/libdvm.so
I/DEBUG   (   56):          #08  pc 0001bd98  /system/lib/libdvm.so
...

Clearly there's a bug in Android here, but it seems to be avoidable.

Don't use your BitmapResource class... you should explicitly recycle() your bitmaps the moment you don't need them any more. I changed your DrawView constructor to this:

public DrawView(Context context, int resId) {
    super(context);
    setImageResource(resId);
}

Since your images are so large - 7MB decompressed! - I also added a System.gc() after the previous image is removed. buttonClickHandler now looks like this:

public void buttonClickHandler(View v) {
    Object tagObj = mSwitchButton.getTag();
    if (tagObj != null && tagObj instanceof ImageView) {
        ImageView iv = (ImageView)tagObj;
        iv.setImageBitmap(null);
            mMainLayout.removeView(iv);
        System.gc();
    }

    addNewViewToLayout(mMainLayout);
}

With these changes your app runs fine for me.

Reuben Scratton
  • 38,595
  • 9
  • 77
  • 86
  • The sample app I posted is the "minimal code to reproduce" derived from a much larger app in which I ran into this problem. I need BitmapResource because there is much more logic in this class in the large scale app. The .recycle call in its finalizer is there because I have many bmp's loaded and unloaded so I cannot explicitly call recycle() because I'll have recycle calls all over the place. However, your suggested solution does solve the problem I posted and made me think about dropping the recycle calls altogether and spread System.gc() calls in some places. Thanks for your help! – Roi Nov 25 '10 at 16:53
0

Dude, try out to clear image cache somehow... I was having similar issue with me. Here is my post SIGNAL 11 SIGSEGV crash Android

Community
  • 1
  • 1
Rohit Mandiwal
  • 10,258
  • 5
  • 70
  • 83