忽略掉遥远的Android2.2及之前版本,本文讨论基于Android4.4,也适用于4.x版本。
项目开发中遇到一个内存溢出问题,抓内存数据分析,发现有的bitmap在java层生成,占用的Dalvik虚拟机堆栈,这也符合我当前粗略的认知,恕本人知识浅陋。原来研究内存,一直认为Android2.2之后的各个版本Android中bitmap都是通过JNI回调到Java层,最后是在Java层真正new出来的bitmap(这个在本文最后取源码做了说明)。可是抓到的信息发现了一个Native stack上的Bitmap,如下图所示。
然后查看资料和源码发现,的确这个是在Native Stack上创建的,因为它是调用BitmapFactory.decodeStream方法,创建出一个bitmap,decodeStream直接调用 JNI 的 nativeDecodeAsset() 来完成decode,这点不同于使用java层的createBitmap。所以这个是在Native层占用的内存。
- private static Bitmap readBitMap(Context context, int resId) {
- BitmapFactory.Options opt = new BitmapFactory.Options();
- opt.inPreferredConfig = Bitmap.Config.RGB_565;
- opt.inPurgeable = true;
- opt.inInputShareable = true;
- // 获取资源图片
- InputStream is = context.getResources().openRawResource(resId);
- return BitmapFactory.decodeStream(is, null, opt);
- }
如图就是源码中的调用,图为BitmapFactory这个源码中decodeStream方法的具体实现,我们可以看到是调用的Native方法,可能有人会问了如果走了else呢,其实else里面的方法跟进去就会发现,也是做了一些处理后,调用nativeDecodeAsset来生成的bitmap。
说到这里我们必须说一个重要的事情,大家千万别以为去调用Native方法就一定是在Native层占用的内存,例如Bitmap.java中的createBitmap也是调用的JNI方法,但其实又反过来回调的Java中的New来做的生成操作。具体的这个地方,我会专门写一篇文章来讲Bitmap和BitmapFactory的源码,从源码中彻底分析一下为什么就是在Native中生成的。