2012-05-30 13:15:51 iteye_20059 阅读数 239

一、 手机端准备工作

1 安装库文件  

 

    所有的  native  内存分配函数  ( malloc calloc , etc.)  都在  Android libc   库中。为了跟踪堆内存的分配,需要使用这个库的特别版本,可以将每次内存开销记录下来。   这些特殊版本的   libc  (  libc_malloc_debug_leak.so  and  libc_malloc_debug_qemu.so  可以在手机中的/system/lib 下查看是否有这两个库 只包含在eng或者user-debug版的 Android中。 如果手机是这两种系统之一,可以跳过下一步。

 

    下载最接近你手机模型和 Android系统版本( 2.3 4.0 等)的 CyanogenMod ROM  。如果没有恰好是你手机的对应版本,那么选择处理器相同的  ( 比如 Tegra2)  Android系统版本(例如 2.3 )都相同的 rom. 。然后从 system/lib   文件夹   抽出 libc_malloc_debug_leak.so   libc_malloc_debug_qemu.so

 

 

    ②以中兴 U880 手机为例,手机本身是移动定制的 Android2.2 系统, CyanogenMod  官网上恰有中兴的 rom,但是系统版本为 2.3.7 ,并且手机需要 root 权限,所以使用 U880 刷机工具,刷U880_2.3.7 root rom

 

 

2 替换库

 

 

CM rom /system/lib 文件夹中抽出   libc_malloc_debug_leak.so  和 libc_malloc_debug_qemu.so

 

 

libc_malloc_debug_leak.so  和  libc_malloc_debug_qemu.so  通过 USB拷到  SDCARD卡根目录下。

 

 

③手机中安 BusyBox  以便使用 cp  命令复制文件。

 

 

       ④PC端命令行中执行

 

adb shell

su

mount 

 

 

    不同手机返回的值不同,如下两例

 

     LG G2x:

     ...

     /dev/block/mmcblk0p1 /system ext3 ro,noatime,errors=continue,data=ordered 0 0

     ...

 

 

    中兴 U880 :

    ...

    /dev/block/ mtdblock11  /system  yaffs2  ro,relatime,barrier=1,data=ordered 0 0

    ...

 

第一部手机将  /dev/block/mmcblk0p1  作为设备,  ext3  作为文件系统类型。

第二部手机将 /dev/block/ mtdblock11  作为设备, yaffs2  作为文件系统类型。

 

 

    ⑤使用上面得到的设备名,和文件系统类型,重新挂载系统分区为读写格式。如下所示:

    LG G2x:

mount -o remount,rw -t ext3 /dev/block/mmcblk0p1 /system

 

    中兴 U880 :

 

mount -o remount,rw -t  yaffs2  /dev/block/ mtdblock11  /system  

 

  ⑥ 把两个库文件从S DCARD 拷到 /system/lib  目录: 

 

cp /sdcard/libc_malloc_debug_leak.so /system/lib/libc_malloc_debug_leak.so

cp /sdcard/libc_malloc_debug_qemu.so /system/lib/libc_malloc_debug_qemu.so 

 

 

  ⑦ 设置权限

 

 

chmod 0644 /system/lib/libc_malloc_debug_leak.so

chmod 0644 /system/lib/libc_malloc_debug_qemu.so 

 

 

3 配置

     替换完新的库文件后,告知系统使用新的库分配内存。

 ②命令行中执行

adb shell

su

setprop libc.debug.malloc 1

 

    支持的参数:

 

 

1  - perform leak detection

5  - fill allocated memory to detect overruns

10 - fill memory and add sentinels to detect overruns

20 - use special instrumented malloc/free routines for the emulator

 

 

     重启框架 ,命令行中继续执行

 

stop
start

 

     如果命令成功,设备将在 1 2 秒后重启, 注意并不是完全重启。 

 

    ④ 检查配置

     输入:

      

getprop

 

 

 

   将会得到很多信息,其中包括:

    ...

    [libc.debug.malloc]: [1]

    ...

 

    说明配置成功

 

 

二、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 的怎么变自己领悟吧。。。

 

2016-02-25 14:14:51 sunnytina 阅读数 4324
第一步: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,

找到相对地址的调用位置



跑脚本,启动和关闭联系人

 for i in `seq 10000`; do adb shell am start com.android.contacts; sleep 1; adb shell am force-stop com.android.contacts; done

第七步:snapshort current native heap usage 对比观察库文件(libhwui.so)

占用的内存是否增加不减少


2017-10-30 11:23:33 zhbpd 阅读数 237
[FAQ05872]如何用DDMS分析native memory leak
2016-08-10
软件分支JB2GB3JB3JB5...

内容

[DESCRIPTION]
native程序如果发生内存问题,一般都比较难查,幸好DDMS有集成native memory leak(仅仅针对app,无法分析mediaserver等非app的进程)功能,通过DDMS可以观察native堆的使用状况以及每个chunk的调用栈等信息,有助于分析native memory leak。
详情可参考:https://source.android.com/devices/tech/debug/native-memory.html

 

[SOLUTION]

1. 请使用eng版本测试。

2. 首先要先开启bionic memory debug 1模式(bionic malloc debug信息可以到网络搜索相关资源),然后连上adb。

    方法如下:

      KK及以前版本:

        adb shell setprop persist.libc.debug.malloc 1
        adb shell reboot

      L及以后版本:

  $ adb shell setprop libc.debug.malloc 1

  $ adb shell stop

  $ adb shell start

    确认是否有开启的方法,查看main log,如有看到以下log,就说明开启成功啦

3. 开启DDMS隐藏的功能 (建议用linux版本的DDMS)

    需要改一个配置. 找到

        linux版本:~/.android/ddms.cfg

        windows版本:C:\Documents and Settings\$user\.android\ddms.cfg

     在ddms.cfg结尾新增一行: native=true 保存后重启ddms

     就可以看到新加的一个'native heap'的tab了

4. 打开DDMS,选择需要查看native memory的进程:

选择process

5. 切换到native heap菜单,填入symbols search path(因为是linux路径,所以windows不能用,这导致第6步的结果没有函数名称信息,只有函数地址!),点击snapshot current native heap usage就可以看到当前native heap的状况
native heap菜单
6. 点击保存后,可以导出一个文本文件,打开后,可以看到一个个记录,它们分配大小*分配次数从大到小排列,所以如果有泄露的话,一般看一个记录就够了,拿到调用栈再结合代码分析可能的泄露点
导出的文本文件
2017-05-04 21:19:49 wuhengde 阅读数 4256
  1. 检查手机上目录system/lib(system/lib64)下存在libc_malloc_debug_leak.so、libc_malloc_debug_qemu.so(eng或者user-debug版本自带)
  2. setprop libc.debug.malloc 1(android7.0以后设置新属性 :setprop libc.debug.malloc.options backtrace https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md)。这里有四种prop可以设置,1是mem leak,5和10是内存越界,20是虚拟机。可悲的是5和10并没有被libc_malloc_debug库完美地支持,所以只有1好用
  3. adb shell stop, start (不要手动关机重启,否则上一步设置的属性值会丢失),getprop libc.debug.malloc查看结果
  4. 在ddms.cfg文件最后增加一行native=true并save。ddms.cfg位于.android目录下。(建议在官网上单独下载SDK工具包,使用里面的ddms)
  5. 打开ddms选择Native Heap页面,点击snapshot按钮。snapshot的过程有点慢。最后能看到每个so占用了多少内存以及百分比。过一段时间snapshot一次就能看到每个so的趋势了。
  6. 分析。snapshot显示了分配内存的地址(记做addressA),这个地址是RAM地址,不是so的相对地址。为了得到相对地址,需要ps一下,找到你的pid,然后cat /proc/pid/maps,找到so的起始地址(记做addressB)。然后拿addressA - addressB,得到相对地址,用addr2line定位到哪一处调用。或者使用objdump -dS libXXX.so > XXX.dump,把so反编译出来,分析XXX.dump,找到相对地址的调用位置(lib64下so:prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin/x86_64-linux-android-addr2line
2014-05-08 19:16:00 wenzongliang 阅读数 40

一、先说DDMS中的Heap的使用,通过可以观察VM中的Java内存,但是无法查看通过JNI分配的内存。

 

直接上图,废话少说。。。

图一:将要查看内存使用情况的项目Update heap

图二:操作项目,通过图表可以很直观查看虚拟机的使用内存

 

二:Android中GC_EXTERNAL_ALLOC的含义(转)

以下内容直接Ctrl C===》Ctrl V

问:

GC_EXTERNAL_ALLOC freed 297K, 49% free 3411K/6663K, external 24870K/26260K, paused 83ms
这里边的每个数字都是什么意思阿?
free 3411K/6663K和external 24870K/26260K,分别都是表示什么的阿?

 

自问自答:

前面Free的内存是VM中java使用的内存,external是指VM中通过JNI中Native的类中的malloc分配出的内存,例如Bitmap和一些Cursor都是这么分配的。
在Davilk中,给一个程序分配的内存根据机型厂商的不同,而不同,现在的大部分的是32M了,而在VM内部会把这些内存分成java使用的内存和 Native使用的内存,它们之间是不能共享的,就是说当你的Native内存用完了,现在Java又有空闲的内存,这时Native会重新像VM申请,而不是直接使用java的。
例如上边的例子
free 3411K/6663K和external 24870K/26260K
如果这时需要创建一个2M的Bitmap,Native现有内存26260-24870=1390K<2048k,因此他就会向Vm申请内存,虽然java空闲的内存是
6663-3411=3252>2048,但这部分内存Native是不能使用。
但是你现在去申请2M的Native内存,VM会告诉你无法分配的,因为现在已使用的内存已经接近峰值了32M(26260+6663=32923 ),所以现在就会成force close 报OOM
所以现在我们要检查我们的native内存的使用情况来避免OOM。

DDMS调试方法

阅读数 538

没有更多推荐了,返回首页