Android开发————分析Native层内存泄漏

来源:互联网 发布:电脑离线地图软件 编辑:程序博客网 时间:2024/06/09 20:27

目录(?)[+]

Android开发——使用DDMS分析Native层内存泄漏

针对Java层的内存泄漏,Android提供了方便的内存泄漏检测工具,例如MAT、LeakCanary。但对于native层开发,要追查C/C++代码的内存泄漏,valgrind等常用工具并不适用。幸好,Google的bionic库提供了新的方法。下面就介绍如何利用DDMS分析Native层的内存泄漏。

检查是否有 libc_malloc_debug_leak.so

所有的Native内存分配函数(malloc,calloc,etc.)都在Android的libc库中。为了跟踪堆内存的分配,需要使用这个库的特别版本,可以将每次内存开销记录下来。这些特殊版本的libc(libc_malloc_debug_leak.so和libc_malloc_debug_qemu.so,在/system/lib 下查看是否有这两个库 ) 。

配置build.prop中的libc.debug.malloc属性值

内存调试靠读取 build.prop 文件中的配置属性 libc.debug.malloc 来控制的,属性值含义如下:

        bionic/libc/bionic/malloc_debug_common.c        libc.debug.malloc    1    检测内存泄漏        libc.debug.malloc    5    分配的内存用0xeb填充,释放的内存用0xef填充        libc.debug.malloc    10   内存分配打pre-和post- 的桩子,可以检测内存的overruns        libc.debug.malloc    20   SDK模拟器上检测内存用

为了开机就启动,可以在开机的时候就设置属性。在build.prop文件中写入libc.debug.malloc属性:

         #adb remount         #vi system/build.prop           增加 libc.debug.malloc=1属性

或者:

        #adb remount        #adb shll        #echo "libc.debug.malloc=1">> system/build.prop

配置DDMS

配置ddms.cfg

在C盘用户的目录下:

        ~\.android\ ddms.cfg 

打开ddms.cfg进行编辑,写入:

        native=true

打开DDMS

在\sdk\tools目录下打开ddms.bat

使用DDMS抓取内存快照

DDMS使用说明

        示意图说明:        1、选中应用进程;        2、打开:Show heap updates,显示堆内存更新;        3、选择:Native heap,Native层堆内存;        4、Snapshot Current Native Heap Usage:抓取内存快照;        5、选择:Group allocations by library ,按照库来显示内存分配;        6、选择:抓取增量(抓取相对于前一次内存快照的增量);        7、选择:Show zygote allocations ,选择源始进程的内存分配;

这里写图片描述

如果按下±(增量)按钮,在点击 Snapshot Current Native Heap Usage 可以比较两次抓取内存之间新分配了哪些空间。查看这个增量结果,通常Percentage和Count值较高的地方都是有可能存在内存泄漏的地方。查看Library项可以拿到可疑库的地址Addr(比如:413afa96)

也有可能直接在DDMS页面的Stack Trace直接查看代码定位: 
这里写图片描述

通过内存地址定位泄漏点

从内存快照中拿到的地址的并不能用来直接定位到分配内存的地方。还需要计算库的物理地址偏移量。

以查找 com.android.browse r的 libwebviewchromium.so 库为例:

    #adb shell    #ps|grep com.android.browser    USER      PID   PPID  VSIZE    RSS     WCHAN      PC         NAME    u0_a18    2571  1883  1423100  93768   ffffffff   b7668cdb S com.android.browser    #cat /proc/2571/maps |grep libwebviewchromium.so    8284f000-82942000 r--p 41391000 08:06 918        /system/lib/libwebviewchromium.so   

由此计算其指令在文件内的偏移量:

    0x413afa96 - 0x41391000 = 0x1ea96        

然后用addr2line就可以查看这条指令对应的源码在哪个文件的哪个位置:

    $ arm-linux-androideabi-addr2line -e    out/target/product/sp8825ea/symbols/system/lib/libwebviewchromium.so 0x1ea96    

可能遇到的问题以及建议

1、打开DDMS后发现目标应用的进程信息没有显示

    解决方案是:    在注册文件的application标签下打开debuggable属性:    <application        android:debuggable="true"

2、整个分析过程要保证ADB不会断开连接; 
3、抓取内存快照时DDMS的过程中不要最好不要操作设备,否则可能很容易导致ANR。

参考文章: 
Android中native进程内存泄露的调试技巧 
Android 内存检测 
Android native heap memory leak 实战(二) — DDMS

0 0
原创粉丝点击