http://phenom.iteye.com/blog/1679198
这篇是翻译的,
此次是实践,是关于Android系统的图片解码的实例
- 文中说到:
- 摄像头在GalaxyNexus拍一张照片有2592*1936像素,如果bitmap使用ARGB_8888配置(2.3默认的),加载这张照片到内存需要消耗约19mb内存,(2592*1936*4bytes)
- 19m的内存对模拟器的16m来说,显然太大了,但对于真实的机器 ,还是可以的
- 至于说Android的图片内存8m,这个不知道是听谁说的,总之我也没有找到标准的答案,有可能是在Android刚出来的时候定义的一个堆大小,我觉得最有可能的是这个值作为图片解码的内存大小,却不是对图片的大小限制的.所以上面的图片是可以解码显示出来的.
- 先说下情况:
- 一张440*17514大小的图片,直接在galaxy上解析,然后得到Bitmap,再放到ImageView中显示,一切正常的.说下galaxy的情况:
- /system/build.prop中的heapsize=64m
- 两种方法,一种是argb_8888配置,一种 是rgb_565
- 实践也表明了,两种图片解码后的效果差不多的,如果不是图像处理,完全可以用rgb_565来处理图片的显示,
- 显然这张图片解析需要29m左右的内存,<64m.所以我觉得Android的内存限制不是只是图片上,而是整个进程的,当进程占用的内存没有超过这个值,就是正常的,而,解析图片通常是最耗内存的操作.
- 在ImageView中显示一张,argb_8888,然后再解码一次,29*2+其它的操作,对象内存,勉强>64m了,只能解码一次.
- 使用rgb_565解码一次15m左右,可以有四次的机会,为什么不是三次呢,29*2<64,但一次解析大图,消耗的其它对象内存也大了.
- 于是修改了/system/build.prop中的heapsize=48m,重启了,
- 再运行,argb_8888一次解码正常的.二次崩溃.
- 使用rgb_565解码,可以两次,三次崩溃.
- 于是修改了/system/build.prop中的heapsize=24m,重启了,
- 再运行,argb_8888一次崩溃.
- 使用rgb_565解码,可以一次,第二次崩溃.
- ,由此可见,不是一张大的图不可以显示出来,通常一张拍摄的照片像2592*1936这样的,有这样的分辨率,就有相应的机器对应,所以内存也就大了,不是所谓的8m.
- 由于只分析了一些实践结果,对系统的代码没有研究,有可能这是不对的,或许
- c对解码图片作了一些内存上的限制.
- 但是可以知道,8m的内存是不对的,即使现在新机器中最烂的也不小于512m的内存,heapsize也>24m,所以对于上面这种大的图片,使用rgb_565解码,是没有问题的.
- final int memClass = ((ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
- System.out.println("memClass:"+memClass);
- 可以得到这个值的大小.
- 最近做的微博程序中大图浏览直接崩溃,内存不足,64m的内存,缓存各种图片64张,图片大小大约是在400*1600,几十张图片加载后就崩溃了.
- 当然如果没有必要,还是缩放一下较好:
- BitmapFactory.Options options = new BitmapFactory.Options();
- 使用缩放的效果明显要比使用rgb_565解码糟糕的多了.
http://www.linuxidc.com/Linux/2013-04/82441p3.htm
明明还有很多内存,但是发生OOM了。
这种情况经常出现在生成Bitmap的时候。有兴趣的可以试一下,在一个函数里生成一个13m 的int数组。
再该函数结束后,按理说这个int数组应该已经被释放了,或者说可以释放,这个13M的空间应该可以空出来,
这个时候如果你继续生成一个10M的int数组是没有问题的,反而生成一个4M的Bitmap就会跳出OOM。这个就奇怪了,为什么10M的int够空间,反而4M的Bitmap不够呢?
这个问题困扰很久,在网上,国外各大论坛搜索了很久,一般关于OOM的解释和解决方法都是,如何让GC尽快回收的代码风格之类,并没有实际的支出上述情况的根源。
直到昨天在一个老外的blog上终于看到了这方面的解释,我理解后归纳如下:
在Android中:
1)、一个进程的内存可以由2个部分组成:java 使用内存 ,C 使用内存 ,这两个内存的和必须小于16M,不然就会出现大家熟悉的OOM,这个就是第一种OOM的情况。
2)、更加奇怪的是这个:一旦内存分配给Java后,以后这块内存即使释放后,也只能给Java的使用,这个估计跟java虚拟机里把内存分成好几块进行缓存的原因有关,反正C就别想用到这块的内存了,所以如果Java突然占用了一个大块内存,即使很快释放了:
C能使用的内存 = 16M - Java某一瞬间占用的最大内存。
而Bitmap的生成是通过malloc进行内存分配的,占用的是C的内存,这个也就说明了,上述的4MBitmap无法生成的原因,因为在13M被Java用过后,剩下C能用的只有3M了。
5、在Android平台下实现OpenGL ES程序的贴图加载操作一般是通过BitmapFactory.decodeResource这个api,然后用系统封装好的 GLUtils.texImage2D函数直接转换为gl贴图即可,方便快捷。但在较新版的Android系统中res中的图片文件夹根据dpi设备分辨率的不同,细分了很多文件夹处理以支持不同设备的分辨率加载对应的图片,如drawable-hdpi,drawable-ldpi,drawable- mdpi等,如果没有注意这个问题而将贴图图片随意安置的话,在decode的时候系统会默认根据设备dpi的不同对目标图片格式解码的同时进行大小调整,也就是说有可能破坏原本已经是2^n大小的贴图图片,导致原本在模拟器上正确的绘图在真机上变成大白板!解决这个问题的方法可以将图片放到不受dpi影响的drawable-nodpi中,或者设置BitmapFactory的选项,不处理dpi相关问题。
6、查询内存限制大小:
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
activityManager.getMemoryClass();
以上方法会返回以 M 为单位的数字,可能在不同的平台或者设备上值都不太一样,比如:HTC G7 默认 24M,Galaxy 36M,emulator-2.3 24M,等等。
相关推荐
Android 内存 OOM 优化和治理,Android 内存泄漏原因详解与应对措施,Android 中的 Bitmap 使用详解,Android 中的 Bitmap 内存治理和优化详解,Android 内存分析命令详解,Java内存模型。Android 内存 OOM 优化和...
Android 内存泄露原因分析。通过原因分析,再接合代码可查明具体原因,发现对策
Android 内存泄露 Mat工具分析。非常好的分析工具讲解
Android内存泄漏简介 不少人认为java程序,因为有垃圾回收机制,应该没有内存泄漏 1.引用没有释放造成的内存泄漏 2.资源对象没有关闭造成的内存泄漏 3.一些不良代码造成的内存压力 4.JNI代码的内存泄漏
该文档来自MDCC 2015中国移动开发者大会。胡凯发表了题为“Android内存优化之5R法则”的主题演讲,欢迎下载!
主要从5个模块入手: 1 java的GC机制以及Android最大堆内存分配 2 Monitors 3 DDMS/Traceview 4 Mat 5 LeakCanary 6 开发中要注意的点。
Android内存管理小结 Android内存管理和分析
Android内存泄漏调试教程,Android内存泄漏调试教程,Android内存泄漏调试教程
android 通过Environment环境 获取手机根目录 读写 文件操作。
android 内存泄露测试.
android 内存分析工具 查看android程序的内存使用状况,并进行分析
二维码简介及Android 内存管理 MAT内存分析工具
android 内存检测 使用eclipse + mat实现android 内存检测
android内存泄露的检测和排查,已经附带一个锁屏内存泄露的例子分析。
android内存优化详解
android内存监测之procrank Android系统中提供了两个命令行工具procrank、procmem用于查看系统中的内存使用情况。这两个工具对于我们分析内存相关问题非常有效。由于Android系统使用的是Linux内核,理论上这样的...
android 内存泄露 分析方法.非常难对应的问题。首先弄明白原理
Android内存泄露分析详解和两种处理方案
一个实用的Android 内存监测悬浮窗,可用于监视某个应用或显示监视信息,本源码中的悬浮窗是用于内存监视器的窗口来用,显示监测到的一些信息,功能说明: 1.用户可任意拖动悬浮窗,自定义位置,并可任意调整窗口...
android内存检测工具,可以让人们在状态栏实时监控当前内存的使用情况,以便做出相应的判断。