From http://blog.chinaunix.net/uid-13614124-id-4054242.html
From http://blog.csdn.net/bd_zengxinxin/article/details/47432223?ref=myread
上一篇讲述了Valgrind,后续发现还有memory leak,但是Valgrind没有给出详细的调用信息,所以只能作罢,寻找其他工具。
从网上了解到DDMS有个隐藏的页面,Native Heap。于是抱着试试看的态度,找来了一台Android设备,刷了CM,这么做的目的是为了得到userdebug/eng版本的ROM(查看命令: adb shell getprop ro.build.type),一般的官方ROM都是user的,没有厉害的debug能力。于是开工!第一步: setprop libc.debug.malloc 1。这里有四种prop可以设置,1是mem leak,5和10是内存越界,20是虚拟机。可悲的是5和10并没有被libc_malloc_debug库完美地支持,所以只有1好用。
第二步,stop, start。这些操作都是在device shell里面做的。设备会快速重启。
第三步,验证prop。getprop看看结果,然后ls一下,去logcat里看一下结果。如果结果都能对的上,那就可以继续了。
第四步,在ddms.cfg文件最后增加一行native=true并save。ddms.cfg位于c:\Users\xxx\.android目录下。
第五步,打开单独的ddms(确保eclipse没有在跑),选择Native Heap页面,点击snapshot按钮。snapshot的过程有点慢。最后能看到每个so占用了多少内存以及百分比。过一段时间snapshot一次就能看到每个so的趋势了。
第六步,分析。snapshot显示了分配内存的地址(记做addressA),这个地址是RAM地址,不是so的相对地址。为了得到相对地址,需要ps一下,找到你的pid,然后cat /proc/pid/maps,找到so的起始地址(记做addressB)。然后拿addressA - addressB,得到相对地址,用addr2line定位到哪一处调用。这里我还用过objdump -dS libXXX.so > XXX.dump,把so反编译出来,分析XXX.dump,找到相对地址的调用位置,一看是_Znwj,这个就是new。其实,搞来搞去最终定位到new,等于浪费表情了。
这个工具远没有Mac Instrument强大,它不能定位到哪个函数占用了多少内存。它能做的就是告诉你哪个so的内存增长减少了,但其实这也很有用,把握好下一步的方向不也很关键吗?
参考:http://bricolsoftconsulting.com/how-to-enable-native-heap-tracking-in-ddms/
二、PC设置
在C:\Documents and Settings\Administrator\.android\ ddms.cfg 文件末尾添加
native=true
三、检查泄露
从SDK\tools 中启动独立的 DDMS ( ddms.bat )可以看见 native heap 选项卡
点击snapshot current... 按钮就可以了,如果按下±按钮,在点击 snapshot current 可以比较两次之间新分配了哪些空间。
有人说使用自己用源码编译出来DDMS 和模拟器,下面的 stacktrace 中的 File 和 Line 列就有值了。我们用的是真机啊。。。没有关系 ~~
找到自己的库函数***.so 后面的 Method 列中的地址。使用 NDK 中的 addr2line 工具,
用法:在命令行中addr2line.exe -e ***\obj\local\armeabi\***.so 地址
注意,一定要是obj 底下的 .so , lib 里面的是不含有符号表的。另外 Method 中的地址一般要将高 3 位置 0 ,80cc6e22 变为 000c6e22 。 80dxxxxx 的怎么变自己领悟吧。。。