在鸿蒙应用开发过程中,Native 内存泄漏是指在 C/C++ 层(通过 NDK 或系统底层)分配的内存,由于未正确释放而导致的泄漏。本文将通过高频泄漏场景和 Native 内存泄漏分析案例,帮助开发者快速定位应用中的 Native 内存泄漏问题。
一、Native 泄漏常见根因及分析流程
(一)常见泄露根因:
1. Native 自身异常导致泄漏
1)基础对象泄漏:使用 malloc/new 等手动分配堆内存后,因未调用 free/delete、提前返回或指针丢失,导致内存无法回收。
2)循环引用:多个 shared_ptr 或 sptr 之间相互持有形成环,导致引用计数无法归零,无法自动析构。
3)生命周期管理不当:通过系统接口申请的原生资源(如文件句柄、NativeWindow、相机会话、编解码器等)在使用完毕后未调用资源对应的释放接口,造成内核或系统服务资源泄漏。
4)过量缓存:为提升性能引入缓存,但未设上限或淘汰策略有缺陷,造成缓存内容持续增长,内存被长期无效占用。
5)业务过载(消费不及时):生产者持续产生数据,而消费者因逻辑错误、阻塞或处理能力不足停止消费,导致缓冲队列无限积压,内存急剧膨胀。
6)业务过载(资源消耗极大):业务一次性申请超大块内存,或同时持有多个高消耗资源(如高分辨率解码、模型纹理),超出设备可用内存上限。
2. ArkTS 引用导致 Native 泄漏
1)跨语言导致泄漏:ArkTS 对象通过 NAPI 持有 Native 对象,因 Finalizer 缺失、未实现或 GC 不可达导致 Native 对象无法释放。
2)标准化排查流程:主要有使用 Native Heap 分析,Native Heap 适合检测复杂泄漏模式(如生命周期管理不当,过量缓存等),需结合调用栈和业务场景分析。
3)使用 Native Heap 分析:
① 复现与日志获取:使用 DevEco Profiler 的 Allocation 模板开启统计模式录制泄漏场景,重复多次操作疑似泄漏场景复现问题。
② 识别泄漏点:点击 Native Heap 泳道,在下方详情 Call Tree 标签页中选择 Created & Existing,查看内存占比较高的调用栈。
③ 分析调用栈:优先在调用栈信息中寻找占比较高且与业务代码强相关的 Symbol Name,即 Category 中为亮色。根据调用栈分析相关代码(双击跳转源码),排查内存未释放原因。
4)代码审查:结合调用栈,梳理相关代码中的内存持有逻辑,定位泄漏根因。
① 业务逻辑无异常:则为 ArkTS 引用导致 Native 泄漏,参考 ArkTS 内存泄漏分析流程。
② 业务逻辑存在异常:修改相关代码。
5)修复与验证:修改代码后,重复步骤1~2,确认内存曲线回归平稳。
使用 Native Heap 分析整体流程图如下:

二、Native 内存泄漏分析案例:使用 Native Heap 分析
(一)案例背景
1. 现象:本案例中,通过反复操作复现问题场景,观察到应用 Native Heap 内存占用呈现"阶梯式持续增长"趋势。
2. 初步判断:使用 Allocation 统计模式录制内存上涨过程,观察 Memory 泳道中的 Native Heap 曲线,呈现出典型的“阶梯式增长”,确认存在 Native 内存泄漏。


(二)分析流程
步骤1. 通过 Allocation 录制泄漏场景
1)基于 DevEco Studio Profiler 插件的 Allocation 模板分析堆内存分配、释放的信息,memory mapping 信息,调用栈信息。这些信息中包括已释放内存和未释放内存。操作步骤如下:启动应用进程,选择 Profiler 工具 → 选择设备与应用进程 → 选择 Allocation 模板 → 创建 Session → 配置录制选项。

2)开启统计模式,同时开启录制异步栈(方便追溯到业务代码)。

3)点击按钮启动录制并复现问题场景。

步骤2. 查看内存分配栈
1)框选 All Heap 中的 Native Heap 子泳道。
2)在下方详情区的“Statistics”页签中选择 Created & Existing。
① All Allocations:框选的时间段的所有分配内存信息。
② Created & Existing:默认选中,在框选范围的起点之后分配的,且在框选范围的终点之前没有释放的内存数据。
③ Created & Released:在框选范围的起点之后分配的,且在框选范围的终点之前已经释放的内存数据。

3)切换到“Call Trees”页签,该部分数据展示了详细的内存分配栈信息。

步骤3. 分析内存分配栈
优先在内存分配栈信息中寻找占比较高且与业务代码强相关的 Symbol Name,即 Category 中为亮色。根据调用栈分析相关代码(双击跳转源码),排查内存未释放原因。可以看到业务代码 malloc 中进行了缓存操作,但未添加 free 方法释放内存。
1)Category 中亮色代表开发者调用栈,其中绿色代表 ArkTS 栈帧,橙色代表 Native 栈帧;灰色代表系统调用栈。

2)优化修复
① 修改代码增加 free 方法释放内存。
② 重新运行应用,再次使用 Allocation 录制内存分配栈。
③ 重复多次操作泄漏场景。
④ 验证结果:
内存曲线无明显上涨。
泄漏问题已修复。

总结
本文针对在鸿蒙应用的开发过程中常见的 Native 内存泄漏问题,给出了清晰的排查路径:Native Heap 结合调用栈深入分析,通过区分“Native 自身异常”与“ArkTS 跨语言引用”两类根因,配合 DevEco Profiler 的 Allocation 模板完成复现、定位、修复与验证的完整闭环。


🔗官网开发者学堂视频(可复制链接至网页跳转)
https://developer.huawei.com/consumer/cn/training/result?type2List=201783644516849879&orderBy=1&courseType=5

🔗社区DFX专题文章(可复制链接至网页跳转)
https://developer.huawei.com/consumer/cn/forum/subject/2101218731402391001


【扫码加入 HarmonyOS DFX 技术交流群】