Android Native内存泄漏案例

2023-05-16

文章目录

    • 背景
    • 现状
    • malloc debug
    • LeakTracer
    • 综合评估
      • 功能
      • 性能
      • 稳定性
      • 治理实践
    • 案例 使用Raphael 定位内存泄漏

项目中遇到一个内存泄漏的情形:usb camera预览时出现了内存泄漏,但内存泄漏很小,测试一晚上泄漏20M内存左右。因此借此机会学习下当前市面上用于Android检测内存泄漏的工具。

背景

Android 平台上的内存问题一直是性能优化和稳定性治理的焦点和痛点,Java 堆内存因为有比较成熟的工具和方法论,加上 hprof 快照作为补充,定位和治理都很方便。而 native 内存问题一直缺乏稳定、高效的工具,仅有的 malloc debug [6]不仅性能和稳定性难以满足需要,还存在 Android 版本兼容的问题。

现状

事实上,native 内存泄漏治理一直不乏优秀的工具,已知的可用于调查 native 内存泄漏问题的工具主要有:LeakTracer、MTrace、MemWatch、Valgrind-memcheck、TCMalloc、LeakSanitizer 等。但由于 Android 平台的特殊性,这些工具要么不兼容,要么接入成本过高,很难在 Android 平台上落地。这些工具的原理基本都是:先代理内存分配/释放相关的函数(如:malloc/calloc/realloc/memalign/free),再通过 unwind 回溯调用堆栈,最后借助缓存管理过滤出未释放的内存分配记录。因此,这些工具的主要差异也就体现在代理实现、栈回溯和缓存管理三个方面。根据这些工具代理实现的差异,大致可以分为 hook 和 LD_PRELOAD 两大类,典型的如 malloc debug [5] 和 LeakTracer。

在这里插入图片描述

malloc debug

malloc debug 是 Android 系统自带的内存调试工具(官方 Native 内存调试 有相关介绍 ) ,虽然没有额外的接入代码,但开启方式和核心功能等都受 Android 版本限制。

地址:https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md
在这里插入图片描述
我们在线下尝试使用 malloc debug 监控西瓜视频 App(配置 wrap.sh)时发现,正常启动时间小于 1s 的机型(Pixel 2 & Android 10),其冷启动时间被拉长到了 11s+。而且在正常使用过程中滑动时的卡顿感非常明显,页面切换时耗时难以接受,监控过程中应用的使用体验极差。不仅如此,西瓜视频在 malloc debug 监控过程中还会遇到必现的栈回溯 crash(堆栈如下,《libunwind llvm 编年史》[8] 有相关分析)。

LeakTracer

LeakTracer 是另一个比较知名的内存泄漏监控工具。

github地址:https://github.com/fredericgermain/LeakTracer

其原理是:通过 LD_PRELOAD 机制抢先加载一个定义了 malloc/calloc/realloc/memalign/free 等同名函数的代理库,这样就全局代理了应用层内存的分配和释放,通过 unwind 回溯调用栈并过滤出疑似的内存泄漏信息。Android 平台上的 LD_PRELOAD 是被严格限制的,因为其没有独立的 unwind 实现,依赖系统的 unwind 能力,也会遇到 malloc debug 遇到的栈帧兼容问题;如果把 LeakTracer 集成到目标 so 里通过 override 方式实现代理,只能拦截到本 so 里显式的内存分配/释放,无法拦截到其他 so 和跨 so 调用的内存分配/释放。通过 native 插桩的方式也是如此,只能监控局部单纯的内存泄漏,无法全局监控内存使用。

综合评估

功能

相对于 malloc debug 和 LeakTracer,Raphael 不仅支持 malloc/calloc/realloc/memalign/free,也支持监控 mmap/mmap64/munmap 等,使监控范围扩展到了线程、webview、Flutter、显存等,基本完全覆盖了 Android 平台上的 native 内存使用场景

性能

Android 平台上的 native 内存泄漏检测通常都是在程序运行过程中进行的,栈回溯和缓存管理会消耗部分 CPU 和内存,带来一定的性能损失。Raphael 可配置的监控能力有很大的伸缩性,性能影响可以限制在可接受范围内,以下数据基于西瓜视频 App 32 位模式评测(中高端机型和 64 位下的性能更高):

  • CPU:32 位模式 & ≥1024 的监控阈值下,在低端机上 CPU 消耗< 3%
  • 内存:32 位模式下默认会有约 16M 的虚拟内存消耗
  • 帧率:32 位模式 & ≥1024 的监控阈值下,低端机上帧率没有明显变化

稳定性

已开源的版本是基于开源 inline hook 实现的,在部分 Android 6 机型上存在卡死问题,除此之外暂未发现其他稳定性问题。此外,字节跳动这边早期的治理实践集中在线下,并基于 Raphael 建设完善了线下的防治体系,更为稳定的版本可以满足线上的监控需求,我们会在后续迭代开源。

治理实践

已开源的版本是基于开源 inline hook 实现的,在部分 Android 6 机型上存在卡死问题,除此之外暂未发现其他稳定性问题。此外,字节跳动这边早期的治理实践集中在线下,并基于 Raphael 建设完善了线下的防治体系,更为稳定的版本可以满足线上的监控需求,我们会在后续迭代开源。

案例 使用Raphael 定位内存泄漏

综合以上分析和接入体验,我们不难发现,这些内存泄漏监控工具在 Android 平台上实际接入时基本都存在以下三个比较典型的问题:

  • 流程繁琐:需要配置 wrap.sh/root permission/setprop 等,受 Android 版本限制
  • 兼容问题:unwind 库存在严重的兼容性问题,libunwind_llvm 无法正确回溯 GNU 编译的栈帧
  • 性能问题:官方的 malloc debug 性能数据是损失 10 倍以上,实测西瓜开启后在中高端机上不可用

定位native的内存泄漏,最开始是使用android原生支持的malloc debug,但是正如上文所说的,我在基于Android10的rk3288的开发板上,正常情况下打开APP时1s内,但是打开malloc debug检测后,直接启动activity超时,因此放弃了malloc debug。后面又使用了LeakTracer,但也正如上文说的:只能拦截到本 so 里显式的内存分配/释放,无法拦截到其他 so 和跨 so 调用的内存分配/释放。通过 native 插桩的方式也是如此,只能监控局部单纯的内存泄漏,无法全局监控内存使用。

最后使用了Raphael来定位native的内存泄漏问题。

详细的说明请参考:

https://github.com/bytedance/memory-leak-detector/blob/master/README_cn.md

// 监控整个进程
Raphael.start(
    Raphael.MAP64_MODE|Raphael.ALLOC_MODE|0x0F0000|1024,
    "/storage/emulated/0/raphael", // need sdcard permission
    null
);

需要注意的是,上面启动检测的参数:1024的意思是只检测超过或等于1024bytes的泄漏,可以根据自己的项目修改该值。如我的项目是将其修改为4.

复现内存泄漏的情形后,使用adb发送广播来抓取目前的内存分配堆栈:

adb shell am broadcast -a com.bytedance.raphael.ACTION_PRINT -f 0x01000000

发送该广播后,在上面开启内存泄漏检测的参数,即上面的/storage/emulated/0/raphael目录下,会生成一份raphael文件,包括maps和report。

然后再隔一段时间发送抓取堆栈的广播:

adb shell am broadcast -a com.bytedance.raphael.ACTION_PRINT -f 0x01000000。

通过对比两次抓取的堆栈文件:report,就可以知道哪里发生内存泄漏了。

比如对比我的项目两次抓取的report:
在这里插入图片描述
根据前面的地址,然后通过addr2line,就可以找到对应发生内存泄漏的代码了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android Native内存泄漏案例 的相关文章

  • MVC三层架构详解

    文章目录 MVC三层架构详解一 MVC是什么 xff1f 1 什么是低耦合 xff1f 2 低耦合有什么好处 xff1f 3 增加代码复用率4 部署快 xff0c 且生命周期成本低5 可维护性高 二 MVC详解1 MVC经典模式2 MVC设
  • Spring-MVC入门

    文章目录 前言一 Spring MVC是什么 xff1f MVC xff1a MVC的工作流程 xff1a 优势 xff1a 二 使用步骤1 创建Maven项目导入依赖 2 配置前端控制器DispatcherServlet 3 配置后端控制
  • 使用阿里云OSS实现图片上传案例

    文章目录 前言一 OSS是什么 xff1f 二 使用步骤1 开通OSS服务2 创建bucket3 创建子账户4 查看帮助文档 xff0c 编写后端代码5 layui前端 总结 前言 在正式的开发环境中 xff0c 类似图片的静态资源一般不会
  • 使用EasyExcel实现Excel的导入导出

    文章目录 前言一 EasyExcel是什么 xff1f 二 使用步骤1 导入依赖2 编写文件上传配置3 配置表头对应实体类4 监听器编写5 控制层6 前端代码 总结 前言 在真实的开发者场景中 xff0c 经常会使用excel作为数据的载体
  • 使用linux部署项目步骤

    文章目录 前言一 服务器环境配置二 数据库导入三 项目打包1 修改项目中的访问路径2 修改db properties的数据库访问路径3 打包4 修改配置 xff0c 启动服务 四 测试总结 前言 今天学习了在服务器中部署项目 xff0c 记
  • IntelliJ IDEA 2023.1 最新变化 【附带ChatGPT教程】

    ChatGPT开源公众号 xff1a https gitee com wy521a astar weixin mp最新变化 2023 1主要更新用户体验编辑器JavaScala分析器版本控制系统构建工具运行 调试框架和技术DockerKub
  • SpringBoot整合Quartz以及异步调用

    文章目录 前言一 异步方法调用1 导入依赖2 创建异步执行任务线程池3 创建业务层接口和实现类4 创建业务层接口和实现类 二 测试定时任务1 导入依赖2 编写测试类 xff0c 开启扫描定时任务3 测试 三 实现定时发送邮件案例1 邮箱开启
  • SpringCloud详解07-Nacos配置管理

    系列文章目录 文章目录 系列文章目录前言一 nacos配置管理二 使用步骤1 基本配置2 导入Nacos配置 三 配置实时刷新总结 前言 接上篇 xff0c 本篇记录Nacos的配置管理 所有的代码都是基于前篇的基础上 一 nacos配置管
  • 使用SpringBoot+JWT+MybatisPlus实现简单的登陆状态验证

    文章目录 前言一 JWT是什么 xff1f 二 使用步骤1 创建项目 xff0c 导入依赖 xff0c 配置 引入工具类2 编写LoginController和UserController3 编写跨域拦截器和token验证拦截器4 全局拦截
  • 浅谈分布式锁

    文章目录 前言一 分布式锁 xff1f 二 实现思路1 存储一个唯一的键2 使用setnx3 给键设置唯一值4 因为超时导致的并发执行4 Redission5 代码实现 总结 前言 最近学习了分布式锁 xff0c 本篇来记录一下 一 分布式
  • 初识STM32单片机

    目录 一 单片机基本认知 二 STM系列单片机命名规则 三 标准库与HAL库区别 四 通用输入输出端口GPIO 五 推挽输出与开漏输出 六 复位和时钟控制 xff08 RCC xff09 七 时钟控制 八 中断和事件 九 定时器介绍 一 单
  • ubuntu16.04 安装ctags,以及一些使用方法的介绍

    vim对于新手来说太不友好了 xff0c 今天折腾ctags折腾了一天终于是有所收获 xff0c 现在来大概介绍一下 首先ctags顾名思义 xff0c 就算给各种库和 cpp文件打标签 xff0c 得到的标签文件给后面omni compl
  • Lottie 框架Native Heap内存爆炸问题解决

    Lottie框架Native Heap内存爆炸问题解决 Lottie 是在 Android 和 iOS上 原生渲染 的After Effects xff08 AE xff09 动画 Lottie是 Airbnb 开源 的支持Android
  • Kali 美化

    配置完Kali xff0c 作为一个正常人 xff0c 对于默认的Gnome的界面都会感觉到一丝丝不满意 xff0c 毕竟太丑了嘛 那么 xff0c 我们需要对Kali美化一下 首先是桌面切换 xff0c 如果你不喜欢Gnome xff0c
  • 安装Arch(含输入法配置)

    先创建一个虚拟机 xff0c 这是我的虚拟机配置 xff1a 然后查看虚拟机的配置文件 xff0c 编辑Arch vmx文件 xff0c 最后一行添加 firmware 61 34 efi 34 保存退出 xff0c 启动你的虚拟机 不出意
  • 使用ViewPager + FragmentStatePagerAdapter 切换后页面数据加载空白或者丢失

    开头直接上结论 xff01 xff01 xff01 xff01 xff01 xff01 第一种原因 xff1a onCreateView中没有做view持久化 viewpage切换的时候Fragment的生命周期会重新走一遍 xff0c 从
  • DataGrip 2023.1 最新变化 【附带ChatGPT教程】

    ChatGPT开源公众号 xff1a https gitee com wy521a astar weixin mp在浏览器中打开最新变化 DataGrip 2023 1 最新变化 处理代码 DBE 4469 xff1a 我们修正了 SQL
  • awk练习题(一)

    文件中包含名字 xff0c 电话号码和过去三个月里的捐款 用 分隔 具体内容如下 xff1a Mike Harrington 510 548 1278 250 100 175 Christian Dobbins 408 538 2358 1
  • UML类图-基本图示法

    类图 xff1a 分如下三层 类的名称 xff08 如果是抽象类则斜体显示 xff09 类的特性 xff08 字段或属性 xff1a 注意前面的符号 xff1a 43 表示public xff0c 表示private xff0c 表示pro
  • 《Design Patterns》Proxy.积跬步系列

    Proxy xff1a 代理模式 先代码 共用接口 xff1a span class token keyword package span h span class token punctuation span l span class t

随机推荐

  • 《Design Patterns》FactoryMethod.积跬步系列

    FactoryMethod xff1a 工厂方法模式 先代码 父类或接口类 xff1a span class token keyword package span h span class token punctuation span ld
  • Java基础总结二

    Java关键字 xff08 特点及关键字作用 xff09 xff1a xff08 1 xff09 被Java语言赋予特殊含义的单词 xff08 53个含两个保留字 xff09 xff08 2 xff09 关键字都是小写 xff08 3 xf
  • SVN快速使用入门

    协同开发时 xff0c 我们时常会听说SVN这个词 xff0c 那么SVN到底是什么 xff1f 又是怎么玩的 xff1f 笔者在初探SVN后进行一个简单的总结 SVN xff1a Subversion的简称 xff0c 是一个开放源代码的
  • 解决Red Hat6.0以上使用yum命报错Loaded plugins: product-id, refresh-packagekit, security, subscription-manager

    什么是yum xff1a Yum xff08 全称为 Yellow dog Updater Modified xff09 是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器 基于RPM包管理 xff0c 能够从
  • Cause: org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found

    org apache ibatis exceptions PersistenceException Error updating database Cause org apache ibatis executor ExecutorExcep
  • [Linux] 记录一次批量开关机操作

    最近公司需要停一部分机器测试下业务稳定性 关停很简单 ansible 就可以了 xff0c 一句命令 ansible guanji m command a 34 shutdown h now 34 定义的关机组 guanji 过了两周 xf
  • 生活篇

    春天 xff0c 一个诗情画意的季节 xff0c 一个生机勃勃的季节 春天 xff0c 为我们带来了温暖 xff0c 为大地带来了生机 在这个春意盎然的季节 xff0c 大自然也开始了她们的春天交响曲 我喜欢三月 xff0c 我也讨厌三月
  • WebStorm 2023.1 最新变化【附带ChatGPT教程】

    ChatGPT开源公众号 xff1a https gitee com wy521a astar weixin mp 观看更新概览视频 在浏览器中打开更新变化 WebStorm 2023 1 最新变化 框架和技术 Astro 支持 备受期待的
  • Ubuntu18.04解决gnome-tweak-tool安装后shell主题提示user-theme extension没有启用的问题

    换用Ubuntu18之后 xff0c 桌面又回到了gnome xff0c 因此找到了gnome tweak tool对桌面进行美化 1 安装gnome tweak tool sudo apt get install gnome tweak
  • 多生产者和多消费者问题

    题目描述 桌子上有一个盘子 xff0c 每次只能向其中放入一个水果 爸爸专门向盘子里面放苹果 xff0c 妈妈专门向盘子里面放橘子 xff1b 只有盘子为空时 xff0c 爸爸或妈妈才可以向其中放入水果 xff1b 仅当盘子里有自己需要的水
  • ssh远程连接服务器常用命令

    命令行下 xff0c 使用ssh 远程登录服务器 ssh 39 用户名 39 64 39 IP地址 39 不用加 39 号 xff0c 这里是为了作区分 39 用户名 39 64 39 IP地址 39 39 s password xxx 项
  • 记录在安卓webview上,gif,apng,pixi.js,lottie-web动画导致闪屏问题

    随着公司项目对动画要求越来越高 xff0c 从由美术提供简单的gif 或者css js开发简单动画变成了使用渲染引擎pixi js使用序列帧动画 xff0c 或者使用龙骨 xff0c spine等更加复杂炫酷的动画 但是发现屏幕在播放动画的
  • 黑苹果_万能OpenCore_0.8.4_EFI

    对于喜欢折腾黑苹果的人来说 xff0c 安装Mac系统就是家常便饭 xff0c 其中最重要的就是EFI的配置 xff0c 配置出一个适合自己电脑的EFI很重要 xff0c 今天发布这篇文章就是为了提供给新加入的伙伴们 xff0c 让更多的伙
  • 黑苹果_OpenCore_0.8.4各项功能精解

    黑苹果已经延续有些年了 xff0c 引导也更新换代过好几次 xff0c 安装黑苹果的第一个条件就是需要拥有一个支持引导苹果系统的EFI xff0c 否则 xff0c 连苹果皮都看不到 xff0c 虽然网上可以直接下载EFI xff0c 但是
  • Github域名解析连接慢问题

    Github域名解析连接慢问题 1 Github访问慢问题2 Github连接解决方案2 1 使用 Gitee 的镜像仓库2 2 配置本地的 hosts 文件 3 DNS域名解析分析3 1 根域名服务器3 1 顶级域名服务器3 1 域名解析
  • C++判断素数(求素数)

    素数又称质数 所谓素数是指除了 1 和它本身以外 xff0c 不能被任何整数整除的数 xff0c 例如17就是素数 xff0c 因为它不能被 2 16 的任一整数整除 思路1 xff1a 因此判断一个整数m是否是素数 xff0c 只需把 m
  • Directx工具修复工具,专注修复C++动态链接DLL文件

    问题 xff1a 方法一 xff1a 可以直接去360管家中搜索DirectX xff0c 然后下载 xff0c 进行修复 方法二 xff1a 如下 xff1a DirectX修复工具最新版 xff1a DirectX Repair V3
  • shell脚本实现在任意虚拟机上 一键重启/关闭 多台虚拟机

    shell脚本实现在任意虚拟机上 一键重启 关闭 多台虚拟机 span class token operator span span class token operator span bin span class token operat
  • ChatGPT体验地址,超多功能,附公众号源码

    GPT 说明效果演示地址体验公众号源码 说明 ChatGPT是一种基于深度学习的自然语言处理 xff08 NLP xff09 技术 xff0c 它可以实现自然的文字对话 ChatGPT是基于预训练的语言模型 xff0c 使用大量的数据和计算
  • Android Native内存泄漏案例

    文章目录 背景现状malloc debugLeakTracer综合评估功能性能稳定性治理实践 案例 使用Raphael 定位内存泄漏 项目中遇到一个内存泄漏的情形 xff1a usb camera预览时出现了内存泄漏 xff0c 但内存泄漏