转载自:www.jianshu.com/p/5c776c01c…
「Bitmap」 可以说是安卓里面最常见的内存消耗大户了,我们开发过程中遇到的oom问题很多都是由它引发的。谷歌官方也一直在迭代它的像素内存管理策略。
从 Android 2.3.3以前的分配在native上,到2.3-7.1之间的分配在java堆上,又到8.0之后的回到native上。几度变迁,它的回收方法也在跟着变化。
1、Android 2.3.3以前
2.3.3 以前Bitmap的像素内存是分配在native上,且不确定什么时候被回收。
需要手动调用Bitmap.recycle()回收。
developer.android.com/topic/perfo…
在 Android 2.3.3(API 级别 10)及更低版本上,位图的后备像素数据存储在本地内存中。它与存储在 Dalvik 堆中的位图本身是分开的。本地内存中的像素数据并不以可预测的方式释放,可能会导致应用短暂超出其内存限制并崩溃。
在 Android 2.3.3(API 级别 10)及更低版本上,建议使用 recycle()。如果您在应用中显示大量位图数据,则可能会遇到 OutOfMemoryError 错误。利用 recycle() 方法,应用可以尽快回收内存。
注意:只有当您确定位图已不再使用时才应该使用 recycle()。如果您调用 recycle() 并在稍后尝试绘制位图,则会收到错误:"Canvas: trying to use a recycled bitmap"。
2、Android 3.0 ~ Android 7.1
虽然3.0~7.1的版本Bitmp的像素内存是分配在java堆上的,但是实际是在natvie层进行decode的,而且会在native层创建一个c++的对象和java层的Bitmap对象进行关联。
3、Android 8.0之后
8.0以后像素内存又被放回了native上,所以依然需要在java层的Bitmap对象回收之后同步回收native的内存。
Tips
实际上app运行时,除了java内存还有native内存,虽然native内存没有明确的限制,但是在32位设备上还是经常会被虚拟内存限制,很多时候native crash都是虚拟内存不足导致,在32位设备32位app大概约束为 3G,64位设备32位app大概约束为4G
当然最近也在说大家要适配64位app,现在一般机型都是64位的,64位机型+64位app,虚拟内存可以认为没有限制了。 这个时候现在就是物理内存了,一般可以关注PSS,很多时候厂商也会去看应用的前后台PSS占用,简单可以通过adb shell dumpsys meminfo查看
所以适配64位,除了改善应用的运行速度,其他对稳定性,尤其是虚拟内存不足导致的native crash改善非常大