前言
- 伴随着业务迭代,App整体占用内存过大,经常发生OOM现象。通过AndroidStudio的Profile发现增长的在native层,所以自己想查看native层在内存中占用情况。
- 下面所有操作过程都是我基于mac系统来做演示的。
如何操作
选择哪种手机
- 用如下命令查看自己手机是否支持配置native层的内存占用情况。
adb shell getprop ro.build.type - 如果执行结果是user,那恭喜你,请选择原谅你的手机。然后用模拟器,大部分模拟器执行结果都是userdebug的,所以直接用AndroidStudio模拟器最省心。
下载低版本的tools文件夹
因为高版本整合了ddms,所以这里我们需要一个低版本的tools。
Linux:https://dl-ssl.google.com/android/repository/tools_r18-linux.zip
Windows:https://dl-ssl.google.com/android/repository/tools_r18-windows.zip
Mac:https://dl-ssl.google.com/android/repository/tools_r18-macosx.zip下载好之后,先备份一下原先sdk下面的tools目录,比如说改个名字什么的,然后把这个新的tools
目录放到sdk目录下
配置DDMS
如果这一步你不配置ddms,进入ddms界面后你会发现并没有Native Heap这个选项。
-
配置文件
Linux: ~.android\ddms.cfg
Windows:c:C:\Users\用户名.android\ddms.cfg
Mac:Home目录下的隐藏文件(.android)
温馨提示:mac下显示隐藏文件是shift+alt+.
如果没找到这个文件的,先打开DDMS一次,就会生成这个文件,在里面加一行:
native=true
问题一:这里配置打开ddms发生了第一个错误,就是端口被占用了,出错图如下:
解决方案一:竟然端口被占用,我们修改端口就完事了呀(mac版本点击ddms的Preferences),把8700改成8701就可以了,解决办法:
libc.debug.malloc属性值含义
- 首先了解下malloc的属性分别代表什么意思。
libc.debug.malloc 1 检测内存泄漏
libc.debug.malloc 5 分配的内存用0xeb填充,释放的内存用0xef填充
libc.debug.malloc 10 内存分配打pre-和post- 的桩子,可以检测内存的overruns
libc.debug.malloc 20 SDK模拟器上检测内存用
配置libc.debug.malloc属性值
- 我这里仅仅是为了排查内存泄漏,所以我选择了配置1。
adb shell setprop libc.debug.malloc 1
adb shell stop
adb shell start(重启生效)
问题二:配置属性出现error现象:
解决方案二:原因是模拟器没开启root模式,执行adb root就可以完美解决这个问题了:
- 如何查看是否已经成功设置
如果下面命令行成功返回xxx(你自己设置的属性值),就代表设置成功了
adb shell getprop libc.debug.malloc
如何使用
-
选择左边的进程,选择右边的Native Heap
-
查看两个内存快照后,内存中新增了哪些so库
如何获取进程的PID
-
下面参考博客可能基于Window or Linux,我这边用mac不行,所以我把我这里如果获取某个进程的PID命令行也写出来。(获取PID是为了计算so库在内存中的地址)
adb shell ps|grep xxxxxxxx(进程的名字)
内存分析结论
- 发现 libimagepipeline.so 占用内存逐渐增大。
- 发现 libgifimage.so 占用内存逐渐增大。
- 后面发现了这两个so库是来自fresco的图片加载缓存的,所以我们需要修改图片缓存的策略 or 清理内存中的图片缓存。