1、HeapSnap 是什么

HeapSnap 是一个定位内存泄露的工具,适用于 Android 平台。

主要特性如下:

对系统负载低

不需要修改目标进程的源代码

支持 Andoroid 上的大多数 native 进程

对函数调用栈自动进行解析,大多情况下不需要找带符号表的程序/库反查地址

支持 Android 多数较新的版本(Android4.0 及以上)

需要 root 权限支持

2、HeapSnap 工具使用

先让目标进程加载 libehapsnap.so,然后再使用 kill 命令发信号给目标进程去保存 heap。下面介绍三种加载 libehapsnap.so 动态库的方法

2.1 使用 heapsnap 工具加载动态库

该方法通过进程注入的方式把代码加载到目标进程内。

把 heapsnap 和 libheapsnap.so 推送到机器(程序也可以推送到其它目录下)adb shell chmod 0777 /data/local/tmp

adb push libheapsnap/libheapsnap.so /data/local/tmp/libheapsnap.so

adb shell chmod 0644 /data/local/tmp/libheapsnap.so

adb push heapsnap /data/local/tmp/heapsnap

adb shell chmod 0755 /data/local/tmp/heapsnap

通过 adb 或者串口登陆目标机器,开启 malloc 调试,并重启目标进程setprop libc.debug.malloc 1

setprop libc.debug.malloc.options backtrace

stop;start

[执行你的应用]

可参考文章Android Libc Debug

加载动态库/data/local/tmp/heapsnap -p -l /data/local/tmp/libheapsnap.so

通过 signal 21 获取目标进程的 heap 信息,并自动保存在/data/local/tmp/heap_snap 目录下 kill -21 [pid]

多次在不同时间点获取目标进程的 heap 信息,并对这些 heap 信息进行比对,从而找出异常的内存分配

也可以选择在加载动态库时直接执行动态库中的函数保存 heap 信息,然后马上关闭动态库.以后每次获取 heap 信息都需要调用相同的命令: /data/local/tmp/heapsnap -p -l /data/local/tmp/libheapsnap.so -o -f heapsnap_save获取到的 heap 信息保存在: /data/local/tmp/heap_snap 目录下

对于已经加载库的进程,也可以这么调用获取 heap 信息.

2.2 LD_PRELOAD 加载动态库

把 libheapsnap.so 推送到机器

adb shell chmod 0777 /data/local/tmp

adb push libheapsnap/libheapsnap.so /data/local/tmp/libheapsnap.so

adb shell chmod 0644 /data/local/tmp/libheapsnap.so

通过 adb 或者串口登陆目标机器,开启 malloc 调试,并重启目标进程(以 mediaserver 为例)

setprop libc.debug.malloc 1

stop media

LD_PRELOAD=/data/local/tmp/libheapsnap.so mediaserver &

也可以配置当前 shell 的环境变量,避免每次都要在目标进程前加"LD_PRELOAD"前缀

export LD_PRELOAD=/data/local/tmp/libheapsnap.so

mediaserver &通过 signal 21 获取目标进程的 heap 信息,并自动保存文件到/data/local/tmp/heap_snap/目录下

kill -21 [pid]

多次在不同时间点获取目标进程的 heap 信息,并对这些 heap 信息进行比对,从而找出异常的内存分配

2.3 目标程序编译时候链接动态库

在目标程序的编译脚本中加入下面这行,然后在你的程序中调用 heapsnap_save(),重新编译好的程序在启动时候会自动链接 libheapsnap.so 库。

缺点就是需要目标程序的源代码及编译环境。

LOCAL_SHARED_LIBRARIES := libheapsnap

可以参考 src/leak_builtin.c 代码

3、解析 backtrace

使用 heapsnap 获得的 heap 信息,已经自动对地址做了解析,如下所示:

Heap Snapshot v1.0

Total memory: 33800

Allocation records: 3

Backtrace size: 32

z 0 sz 4096 num 8 bt 0000007f9a2b0e14 0000007f9a37f534 00000055828338bc 000000558283379c 0000007f9a37f6b0 0000005582833810

#00 pc 0000000000008e14 /system/lib64/libc_malloc_debug_leak.so (leak_malloc+408)

#01 pc 0000000000019534 /system/lib64/libc.so (malloc+24)

#02 pc 00000000000008bc /system/bin/leak_test

#03 pc 000000000000079c /system/bin/leak_test (main+28)

#04 pc 00000000000196b0 /system/lib64/libc.so (__libc_init+104)

#05 pc 0000000000000810 /system/bin/leak_test

通常,heapsnap 所解析出来的 backtrace 信息已经能够大致判断出泄露点了。

但是有时候你需要更精确的解析,如果你手上有设备所对应的 android 环境,那么可以使用 android 提供的工具进行 backtrace 地址解析

android 6 及早期版本$ development/scripts/stack heap.txt > heap_info.txt

android7 以后的版本$ development/scripts/native_heapdump_viewer.py heap.txt > heap_info.txt

解析后的信息如下:

BYTES %TOTAL %PARENT COUNT ADDR LIBRARY FUNCTION LOCATION

0 0.00% 0.00% 0 APP

107808 100.00% 100.00% 198 ZYGOTE

107800 99.99% 99.99% 197 5d1b2c0678 /system/bin/leak_test do_arm64_start external/heapsnap.git/leak_test.c:?

107800 99.99% 100.00% 197 77cd006594 /system/lib64/libc.so __libc_init /proc/self/cwd/bionic/libc/bionic/libc_init_dynamic.cpp:109

98304 91.18% 91.19% 24 5d1b2c073c /system/bin/leak_test foo /proc/self/cwd/external/heapsnap.git/leak_test.c:9 (discriminator 1)

8472 7.86% 7.86% 172 5d1b2c0764 /system/bin/leak_test main /proc/self/cwd/external/heapsnap.git/leak_test.c:22

8472 7.86% 100.00% 172 77cd02a084 /system/lib64/libc.so sleep /proc/self/cwd/bionic/libc/upstream-freebsd/lib/libc/gen/sleep.c:58

8472 7.86% 100.00% 172 77cd05756c /system/lib64/libc.so nanosleep /proc/self/cwd/bionic/libc/arch-arm64/syscalls/nanosleep.S:7

8472 7.86% 100.00% 172 77cd2206bc [vdso] ??? ???

...

注意: 对于 android7/8/9 版本,需要打下面这个补丁,才能正常解析 heapsnap 保存下来的 heap 信息

$ cd android/development

$ patch -p1 < android_7_8_9_development_script.patch

4、注意点

注意 arm/arm64 版本的区别,如果调试的目标程序是 32bit,请使用 arm 版本的 heapsnap 程序和 libheapsnap.so 库;如果调试的目标程序是 64bit,就要使用 arm64 版本的 heapsnap 程序和 libheapsnap.so 库。

对于 android 9/10 及以后的版本,若你调试的对象是/vendor目录下的程序,那么你必须把libheapsnap.so文件也放到/vendor 目录下,否则加载 libheapsnap.so 文件会失败。

对于 android 7/8/9 版本,在这几个版本中把获得的 heap 信息,以及解析脚本"native_heapdump_viewer.py"存在问题,heapsnap 对 heap 信息有做了修正;也提供了补丁"android_7_8_9_development_script.patch"修正"native_heapdump_viewer.py"脚本的问题。

LD_PRELOAD 环境变量只对当前的 shell 有效,如果进程是做为 service 由 init 启动,需要先 stop 该进程,然后在 shell 下启动进程.

一些具有 AT_SECURE 属性的进程或者环境,它们在 link 处理过程中会忽略掉 LD_PRELOAD 参数,即 LD_PRELOAD 对该类进程或环境不起作用.

使用 heapsnap 需要root 权限.

android堆内存解析,heapsnap HeapSnap 是一款针对 Android 进程堆内存进行追踪、定位,以便查出泄露位置的工具 @codeKK c开源站...相关推荐

  1. android+n+xperia+z3,索尼Z3成为首款升级Android 7.0机型

    访问购买页面: 索尼将成首款升级Android N开发版机型 目前只有D6603.D6653这两个版本的Xperia Z3才有资格参与,但不排除未来加入更多版本乃至手机型号. 索尼Z3初尝Androi ...

  2. 基于android新闻阅读器,Readian News是一款基于Android和网络的新闻阅读器,可让您掌控一切...

    主流媒体有其用途,但这些新闻出版物在很大程度上忽略了许多主题和兴趣.想要跟上赛博朋克2077游戏,Mozilla Firefox的Proton设计更新或您最喜欢的足球运动员西蒙·恩格尔曼(Simon ...

  3. android 混音 源码,FFmpegAndroid android 端基于 FFmpeg 实现音频剪切、拼接、转码、混音、编解码;视频剪切、水印、截图、转码、编 @codeKK c开源站...

    android 端基于 FFmpeg 库的使用 添加编译 ffmpeg.shine.mp3lame.x264 源码的参考脚本 目前音视频相关处理: 音频剪切.拼接 音频混音 音频转码 音视频合成 音频 ...

  4. android 混淆工具下载,Obfuscapk:一款针对Android应用程序的黑盒混淆工具

    Obfuscapk是一款模块化的Python工具,它可以帮助研究人员在无需应用程序源代码的情况下对Android App进行混淆处理.Obfuscapk使用了apktool来对原始APK文件进行反编译 ...

  5. android差分升级原理,BigNews Android 增量更新框架差分包升级 @codeKK c开源站

    支持增量包/差分包/升级包 原理:在服务器端使用 bsdiff 工具将新老安装包的差异打包为一个体积较小的差分包/升级包,然后在 App 端通过 bspatch 工具(和 bsdiff 配套的)用差分 ...

  6. 编程易筋经:内存解析之实例讲解

    一.引言 作为一名优秀的编程人员我们不能会敲代码,我们还必须要懂得那些代码在计算机中是如何一步步执行的.只有这样我们才能写出经久不衰,经得起考验,更优秀的代码,开发出更好的软件.我们都知道任何代码的执 ...

  7. 内存分配的原理__进程分配内存有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)

    如何查看进程发生缺页中断的次数? 用ps -o majflt,minflt -C program命令查看. majflt代表major fault,中文名叫大错误,minflt代表minor faul ...

  8. 如何让python进程常驻内存_常驻内存程序--python+rrd监控cpu

    问题1: A. 编写一个C程序,常驻内存且占用100M的内存. #include #include #include #include #define MAXFILE 65535 #define si ...

  9. brk16_Linux进程分配内存的两种方式--brk() 和mmap()

    如何查看进程发生缺页中断的次数? 用ps -o majflt,minflt -C program命令查看. majflt代表major fault,中文名叫大错误,minflt代表minor faul ...

最新文章

  1. 《C++面向对象高效编程(第2版)》——导读
  2. ssh配置公钥_如何使用公钥认证免密码ssh远程登录Linux服务器
  3. 计算机控制系统从本质上看,计算机控制系统测试题.doc
  4. JS以及CSS对页面的阻塞
  5. 模块导入以及书写规则
  6. php$this-conn可以不先定义吗,CodeIgniter 是不是支持PDO 查询?还是本来就不支持
  7. 伯乐发卡系统源码 可用
  8. 【Selenium 爬爬 猪 八 戒】
  9. 汽车之家港股上市发行价定为176.3港元 募资35.6亿港元
  10. 最小路径问题_BFS
  11. OpenCV精进之路(零):HighGUI——读写XML和YML文件
  12. 计算机组成原理—读写周期与半导体只读存储器
  13. centos7 mysql5.6.35_Centos7.2.1511 编译安装Mysql5.6.35
  14. 好用的网络拓扑绘制软件亿图图示安装以及使用
  15. 河南计算机职称不考了,河南省评定中级工程师职称是否还要求计算机应用能..._职称英语考试_帮考网...
  16. qrect在图片上显示矩形框_教你一招把身份证扫描到手机上,非常清晰!真是太方便了...
  17. 云智慧全智能计算机,东方所推出INV3062T型云智慧采集系统
  18. 未来科技蒲公英大飞_大烟草的下跌告诉我们关于大科技的未来
  19. 继续魔改TCP BBR
  20. AccessibilityService——实现微信切换账号功能

热门文章

  1. 一台计算机英语美式发音,美式英语发音课程(视频+文本) 第69期:Want和Won't的发音对比...
  2. 计算机学院机考,东华大学2015年计算机学院研究生复试上机考真题.docx
  3. Android TextView 字体 加粗以及判断是否加粗
  4. ArcEngine旋转IRotateTracker
  5. 蓝桥ROS机器人之C++基础开发第一个程序
  6. mysql的版本是什么_mysql版本号是什么意思?
  7. matlab fisher检验,FISHER线性判别MATLAB实现.doc
  8. 国培南通之行的感悟——(其三)
  9. 人工智能/数据科学比赛汇总 2019.6
  10. js修改div标签中的内容