Leaked unreferenced byte[] originally from bitmap

2020-03-31 10:16发布

I have a memory leak of bitmaps causing out of memory. I ran the tests on Android 5.0 (Samsung S5). I have investigated the issue using Android Studio (1.5.1 + 2.0.0 Preview 7). The HPROF memory dump show that there are multiple byte[] which correspond exactly to a particular huge bitmap I use temporarily. If I make sure I keep references to the bitmap then Android Studio shows me a Bitmap with 11MB dominating size and a byte[] with 11MB Shallow size. If I don't keep references to the bitmaps then some of the bitmaps become garbage collected and some end up as byte[] without incoming references (ie. no parents) as shown in image.

enter image description here

I have tested my app enough to know with reasonable confidence that this 11MB byte[] is a roughly 2891x1000x4 bitmap I have had in memory. Some smaller bitmaps also get leaked and show up with no incoming references.

The bitmaps above are allocated in a subactivity. If I return to the parent activity (in same process and thus dalvikVM) and force 2x GC then memory is released. Multiple manual GC's does not release the memory before quitting the sub-activity.

It seems to be independent on whether I run bitmap.recycle() or not. It happens very rarely if I just stand in the same place in the app and run the code generating the huge bitmap out of the same view. If I move around the app and generate the bitmap from different views its a lot more frequent, like from 50% leaks to 10% leaks.

  • Is it an Android bug?
  • Do I use the bitmaps wrong in some way and Android studio just fails to show me a correct view of the memory?
  • Is my understanding correct that if there are no parents in the reference tree below (see image), then the memory should be released by garbage collector (hence its an Android Bug or studio bug or hprof dump-bug?)

1条回答
啃猪蹄的小仙女
2楼-- · 2020-03-31 10:27

I found a solution to the leak, though Android Studios reporting of the unreferenced byte[] is still a mystery.

It appears that the ImageView in which i did

imageView.setImageBitmap(bitmap)

will prevent GC of the bitmaps underlying byte[]. bitmap.recycle() does not help, nor does unbinddrawables() as written about in numerous locations

if (imageView.getBackground() != null) {
    imageView.getBackground().setCallback(null);
}
setImageBackground(imageView, null);
imageView.setImageBitmap(null);
imageView.setImageDrawable(null);

When I removed the view from the viewhiearchy and removed all my own references to the view, then the byte[] was GC'ed and the leak was gone.

查看更多
登录 后发表回答