注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

创新改变世界

you changed the world

 
 
 

日志

 
 

Android Bitmap开发之旅--OOM探索  

2014-05-14 09:59:40|  分类: android |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

1 问题

谈到Bitmap就必须和Android虚拟机内存扯上关系。在Android开发中,内存使用一直是围绕Bitmap开发的难点。虽然Java有专门的垃圾回收机制(GC),但是在Bitmap使用中,常常会遇到过OOM(out of memory)异常,相信有Android多媒体开发经验的朋友体会尤为深刻。

首先来分析一下OOM的原因,当我们使用BitmapFactory来decode一张3.5M大小的图片(3456*2304),我们decode出来的Bitmap的大小是多少呢?

Bitmap大小计算公式: Size = image.width * image.height * Config

(Config 参数为图片的编码器,常见的图片编译器有 ALPHA_8、RGB_565、ARGB_4444(Deprecated)、ARGB_8888)

RGB_565解码器占用2 byte       ARGB_8888 解码器占用4byte       

当图片采用ARGB_8888编码器时,Config为4,那么decode后的Bitmap大小为:3456 * 2304 * 4,换算成M为30.375M,My God整整是原来图片的8.6785倍,因此当我们使用Bitmap时稍有不慎,造成OOM简直成了理所当然了。

2 分析

难道编写Android的大牛们没有考虑到这个问题?

答案肯定是考虑到了的。在阐述接下来的问题之前,要给大家洗洗脑。很多人都认为Android应用所占用的内存就是虚拟机(Dalvik)所占用的内存。其实Android应用所占用的内存由Dalvik虚拟机内存和Native Memory内存组成。因此,当我们在进行多媒体开发的时候遇到OOM时,Java层代码已经做到perfect了(代码优化到极致),还是存在OOM异常的时候。可以利用Native Memory(本地内存)来解决OOM异常。

利用Native Memory?

我没听错吧?Davik 虚拟机内存和 C/C++的Native Memory共享?真是什么高难度技术,研究了半天源码,还是没有看出大牛们是怎么实现。具体实现的我们先放一边,(如果大家对内存共享感兴趣的话,可以去研究一下,顺便告诉我以下,在此先谢过了)我们的目的是怎样使用Native Memory内存。换句话说我们需要怎样将Bitmap所占用的内存挪到Native Memory内存中,这才是我们的重点。

查看应用占用的内存(Dalvik 虚拟机和Native Memory)大小的方式如下所示:

  1. # adb shell dumpsys meminfo com.jony.actionbar  

3 实现

首先我们来看看使用Dalvik虚拟机来的decode一张Bitmap所占用的内存大小。

使用图片信息: Storage: 3.5M图片(3456*2304)

网上有很多人说使用decodeStream()方法,不需要使用Java层decode Bitmap,因此可以节省Java层虚拟机的内存。我不知道这些人是凭空想象,还有有什么证据来说明他们的结论。根据我的实验以及源码的分析,BitmapFactory的decode方法都是调用的Java的Native方法。因此网上的这种说法正确性还有待考证。

方法一:

  1. AssetManager am = getAssets();  
  2. InputStream is = am.open("high_pixel_img.jpg");  
  3. Bitmap bitmap = BitmapFactory.decodeStream(is);  

Dalvik虚拟机占用的内存如图3-1所示:


                                                                            图 3-1

(备注:其中红色标记的为当前Dalvik虚拟机所占内存)

使用#adb shell dumpsys meminfo com.jony.bitmaptest 命令查看Dalvik虚拟机内存和Native memory使用情况如图3-2所示:

                                                                           图 3-2

方法二:

  1. try {  
  2.             BitmapFactory.Options options = new BitmapFactory.Options();  
  3.             options.inPreferredConfig = Config.ARGB_8888;  
  4.             options.inPurgeable = true;//允许可清除  
  5.             options.inInputShareable = true;// 以上options的两个属性必须联合使用才会有效果  
  6.             AssetManager am = getAssets();  
  7.             InputStream is = am.open("high_pixel_img.jpg");  
  8.             Bitmap bitmap = BitmapFactory.decodeStream(is,null,options);  
  9.             imageView.setImageBitmap(bitmap);  
  10.         } catch (IOException e) {  
  11.             e.printStackTrace();  
  12.         }  

Dalvik虚拟机占用的内存如图3-3所示:


                                                                                       图 3-3 

使用#adb shell dumpsys meminfo com.jony.bitmaptest 命令查看Dalvik虚拟机内存和Native memory使用情况如图所示:

                                                                                 图 3-4


结合以上信息可以分析出:采用方法一Decode一张图片的时候Bitmap占用的是Dalvik虚拟机的内存;采用方法二Decode一张图片的时候Bitmap占用的Native memory的内存空间。因此在使用Bitmap的时候,可以根据业务的需求采用不同的内存占用方式,完美的解决OOM问题。

文章来源:http://blog.csdn.net/weihan1314/article/details/8016759


正确性有待考证?
  评论这张
 
阅读(112)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017