Android Bitmap处理和内存管理与垃圾回收
2012-11-24 11:13
211 查看
Android3.0之前的手机,通过DDMS观看Heap信息的时候不显示native部分分配的内存大小,如图所示,加载了一张7M多的图片,但是显示分配Allocated才2M多。但是native分配的内存大小是算在heap上的,所以当heap大小显示的不是HeapMaxSize的时候,也有可能oom。
下图是Android3.0之前Bitmap的内存管理方式。
3.0以后情况。
3.0以后Bitmap内存管理方式。
3.0以后Bitmap分配的内存是受GC管理的内存,分配站Heap上,可以通过GC回收。3.0之前是freed via recycle() or finalizer。
3.0以前LogCat会出现类似external_alloc相关字样,应该就是上图中Native中分配的内存。
还有GC_EXTERNAL_ALLOC,表示GC to try to reduce heap footprint to allow more non-GC'ed memory.
可以通过GC_EXPLICIT freed <1K, 50% free 2718K/5379K, external 19447K/21495K, paused 54ms,观察到external的内存占用,使用了19447K,总共21495K。free后面显示的是分配在Heap上的内存。
网上有这么说的“external是指VM中通过JNI中Native的类中的malloc分配出的内存,例如Bitmap和一些Cursor都是这么分配的”。
而且发现,通过BitmapFactory decode的时候,Android4.0和Android2.3分配的内存空间是不一样的,Android4.0分配的空间是Android2.3的2倍。(没有具体考察具体的分界线是哪个版本)
这个可以在decode的时候通过设置Options来更改,inPreferredConfig属性决定了,Bitmap.Config类型,Config有常用的有RGB_565,ARGB_8888两种,正好对应了刚才说的情况。RGB_565是每个像素用2个字节存储,只存储R、G、B信息,分别占用5、6、6个bit,没有alpha信息。而RGB_8888是每个像素用4个字节存储,A、R、G、B分别用8bit存储。当然这种图片的质量更高。
还有一个疑问是我的图片是7.8M的一张图片,但是加在到内存占用了17M多的内存,这个正是刚才说的,比如这个图的尺寸是3488 × 2616,所以就有3488 × 2616个像素点,使用RGB_565的时候,每个像素点用2个字节存储。3488 × 2616 x 2正好就是17M多。
加载大图片的通常做法是,先通过设置Options.inJustDecodeBounds属性为true,这样decode的时候只会decode图片尺寸信息,通过Options.outHeight和outWidth取得。然后和希望的最大宽高值计算出inSampleSize。
The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels.
也就是说横向和纵向用sample size个点表示一个点。例如,inSampleSize == 4,返回一个原来宽高的1/4的图片,有原来像素数的1/16。
另外,不同机型的Heap最大大小是不一样的,一些机型
Heap size limits
– G1: 16MB
– Droid: 24MB
– Nexus One: 32MB
– Xoom: 48MB
具体手机可以通过ActivityManager.getMemoryClass()来获取Heap大小。Heap大小是动态分配的,有一个最小的初始值,然后会随内存分配动态增长,这是和标准jvm一样的。
这个值也可以通过更改/system/build.prop文件中的dalvik.vm.heapsize来改变。
对于GC的方式也是有区别的:
• Pre-Gingerbread GC:
– Stop-the-world
– Full heap collection
– Pause times often > 100ms
• Gingerbread and beyond:
– Concurrent (mostly)
– Partial collections
– Pause times usually < 5ms
最后,分析内存情况的话可以使用DDMS,dump出内存使用的情况,然后使用Eclipse Memory Analyzer (MAT)来分析内存使用情况。
Google IO 11有个Session是“memory_management_for_android_apps”部分参考了这个Session的内容。
下图是Android3.0之前Bitmap的内存管理方式。
3.0以后情况。
3.0以后Bitmap内存管理方式。
3.0以后Bitmap分配的内存是受GC管理的内存,分配站Heap上,可以通过GC回收。3.0之前是freed via recycle() or finalizer。
3.0以前LogCat会出现类似external_alloc相关字样,应该就是上图中Native中分配的内存。
还有GC_EXTERNAL_ALLOC,表示GC to try to reduce heap footprint to allow more non-GC'ed memory.
可以通过GC_EXPLICIT freed <1K, 50% free 2718K/5379K, external 19447K/21495K, paused 54ms,观察到external的内存占用,使用了19447K,总共21495K。free后面显示的是分配在Heap上的内存。
网上有这么说的“external是指VM中通过JNI中Native的类中的malloc分配出的内存,例如Bitmap和一些Cursor都是这么分配的”。
而且发现,通过BitmapFactory decode的时候,Android4.0和Android2.3分配的内存空间是不一样的,Android4.0分配的空间是Android2.3的2倍。(没有具体考察具体的分界线是哪个版本)
这个可以在decode的时候通过设置Options来更改,inPreferredConfig属性决定了,Bitmap.Config类型,Config有常用的有RGB_565,ARGB_8888两种,正好对应了刚才说的情况。RGB_565是每个像素用2个字节存储,只存储R、G、B信息,分别占用5、6、6个bit,没有alpha信息。而RGB_8888是每个像素用4个字节存储,A、R、G、B分别用8bit存储。当然这种图片的质量更高。
还有一个疑问是我的图片是7.8M的一张图片,但是加在到内存占用了17M多的内存,这个正是刚才说的,比如这个图的尺寸是3488 × 2616,所以就有3488 × 2616个像素点,使用RGB_565的时候,每个像素点用2个字节存储。3488 × 2616 x 2正好就是17M多。
加载大图片的通常做法是,先通过设置Options.inJustDecodeBounds属性为true,这样decode的时候只会decode图片尺寸信息,通过Options.outHeight和outWidth取得。然后和希望的最大宽高值计算出inSampleSize。
The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels.
也就是说横向和纵向用sample size个点表示一个点。例如,inSampleSize == 4,返回一个原来宽高的1/4的图片,有原来像素数的1/16。
另外,不同机型的Heap最大大小是不一样的,一些机型
Heap size limits
– G1: 16MB
– Droid: 24MB
– Nexus One: 32MB
– Xoom: 48MB
具体手机可以通过ActivityManager.getMemoryClass()来获取Heap大小。Heap大小是动态分配的,有一个最小的初始值,然后会随内存分配动态增长,这是和标准jvm一样的。
这个值也可以通过更改/system/build.prop文件中的dalvik.vm.heapsize来改变。
对于GC的方式也是有区别的:
• Pre-Gingerbread GC:
– Stop-the-world
– Full heap collection
– Pause times often > 100ms
• Gingerbread and beyond:
– Concurrent (mostly)
– Partial collections
– Pause times usually < 5ms
最后,分析内存情况的话可以使用DDMS,dump出内存使用的情况,然后使用Eclipse Memory Analyzer (MAT)来分析内存使用情况。
Google IO 11有个Session是“memory_management_for_android_apps”部分参考了这个Session的内容。
相关文章推荐
- Android手动回收bitmap,引发Canvas: trying to use a recycled bitmap处理
- android内存管理,垃圾回收策略的疑惑
- Android手动回收bitmapisRecycled(),引发Canvas: trying to use a recycled bitmap处理
- Android手动回收bitmap,引发Canvas: trying to use a recycled bitmap处理
- Android知识点:process属性、openOrCreateDatabase、URLEncoder.encode、垃圾回收、 缓存处理、断点续传 推荐
- Android 虚拟机,内存管理,垃圾回收 相关
- Android手动回收bitmap,引发Canvas: trying to use a recycled bitmap处理
- Android虚拟机内存管理垃圾回收【转】
- Android手动回收bitmap,引发Canvas: trying to use a recycled bitmap处理
- android内存管理,垃圾回收策略的疑惑
- JVM内存管理及垃圾回收机制
- c++ 内存管理变革 之 新视角:具垃圾回收能力的Allocator
- Android ,Bitmap ,Drawable,图像缩放,圆角处理,倒影
- (4.4.1.8) android垃圾回收机制及程序优化System.gc
- JVM学习笔记(三)------内存管理和垃圾回收
- .Net 垃圾回收和大对象处理 内存碎片整理
- Android的垃圾回收机制(android refbase类(sp wp))
- android进阶篇一、Bitmap内存管理及各版本区别
- Android学习之——(2)项目中的网络连接相关以及Bitmap处理学习
- JVM内存管理和JVM垃圾回收机制