当前位置: 首页 > news >正文

DevEco Studio Profiler 升级:高效解决 ArkTS 与 Native 交互内存泄漏难题

本原创文章帖发布在华为开发者联盟社区,欢迎开发者前往访问评论交流,更多与该内容相关讨论,请点击原帖查看:

DevEco Studio Profiler 升级:高效解决 ArkTS 与 Native 交互内存泄漏难题-华为开发者话题 | 华为开发者联盟

在鸿蒙 ArkTS 与 Native(C/C++)交互的开发场景中,ArkTS 对象被 Native 引用导致的内存泄漏问题是开发者的一大痛点。

这类问题的传统定位方式高度依赖开发者具备深厚的技术积累,不仅要求开发者要精通 ArkTS 引擎垃圾回收机制、在 NAPI 交互模型等基础理论,还要深入理解应用代码的实现细节,尤其在应用由多个模块组成、模块间依赖关系复杂的场景下,问题定位复杂度倍增。

这种高门槛导致许多开发者,尤其是初学者,在面对 ArkTS 对象被Native引用导致内存泄漏问题时往往无从下手,只能通过参考典型案例、分析大量业务代码来进行问题定位,效率较为低下。

为了帮助开发者更高效地定位和解决此类内存泄漏问题,DevEco Studio 的 Profiler 工具迎来了重大升级!本次更新增强了 Allocation 内存分析能力,新增了 ArkTS Snapshot 泳道,支持 Local Handle 和 Global Handle 采样模式,在跨语言调用场景中,打通 ArkTS 和 C++ 语言边界,内存泄漏大小和泄漏对象信息易观测,问题定位效率倍增。

本文中,我们将结合 DevEco Studio Profiler 工具,系统梳理 ArkTS 对象被Native 引用导致内存泄漏的定位思路、实操步骤与实践案例。

为什么ArkTS对象会被Native“锁死”?

ArkTS 对象被 Native 引用导致内存泄漏的根因在于 Native 代码通过napi_ref 或不当使用 napi_value ,导致长期持有 ArkTS 对象,形成了“隐形强引用”,阻断了 ArkTS 引擎的垃圾回收。

在 NAPI 交互模型中,Native 代码引用 ArkTS 对象主要依赖两种句柄:Local Handle (napi_value): 通常指在 Native 代码执行上下文中创建的、作用域较短的引用,由 handle scope 来管理。

Global Handle (napi_ref): 这是一种由开发者自行管理生命周期的强引用。

ArkTS 引擎的垃圾回收是基于“可达性分析”算法实现的,当 ArkTS 侧所有引用(变量、闭包等)被清除后,对象理论上应被回收。一旦 Native 代码通过 napi_ref 或 napi_value不当持有该对象,这两种句柄会在 GC 图中成为一个“根节点”。 即使 ArkTS 侧已彻底断开引用,GC 仍会判定该对象“可达”,导致无法回收。久而久之,未释放的句柄堆积,演变为内存溢出问题。

升级后的Allocation内存分析工具能做什么?

在定位 ArkTS 对象被 Native 引用引发的内存泄露问题时,开发者常受限于工具或日志信息不足,难以追溯具体是哪块 Native 代码在持有着它。这导致泄漏边界模糊、引用链断裂,定界分析极为困难。升级后的 Allocation 工具实现了关键突破——支持 ArkTS 对象和 Native 引用分配调用栈 的双向关联,可精准追溯持有权属,快速还原跨语言引用关系链,大幅降低定位门槛。

ArkTS内存泄漏分析案例

案例背景

现象:本案例中,通过复现‘首页至消息页’的反复进出操作,观察到应用内存占用呈现"阶梯式持续增长"趋势。在循环操作10次后,应用出现显著卡顿现象。

初步判断:典型的“阶梯式内存增长”,高度疑似内存泄漏。

分析流程

步骤1Memory泳道确认泄漏

1、打开 DevEco Studio,连接真机,点击 Profiler 工具 Realtime Monitor(也可使用 snapshot 模板的 Memory 录制观察,以下是使用 Realtime Monitor 观察)。

2、启动应用,选择设备与应用进程。

3、点击录制按钮,在设备上重复操作:进入消息页面 → 停留 2 秒 → 返回首页,重复多次。

4、观察内存曲线:

• 正常预期:每次退出后内存回落至基线附近,整体呈锯齿状。

• 实际现象:曲线呈阶梯状上升,多次操作后内存增长至 314.1 MB 且无明显回落。

✅ 确认存在内存泄漏,进入下一步。

步骤2:堆快照对比定位异常对象

1、在 Profiler 中切换到 Snapshot 模板,请参考使用 Snapshot 模板基本操作:

• 🔗 Snapshot 模板基本操作:文档中心

选择 Profiler 工具 → 选择设备与应用进程 → 选择 Snapshot 模板 → 创建Session → 启动录制

2、抓取快照1首次在进入消息页前,点击“Take Heap Snapshot”。

3、抓取快照2重复进出消息页面 7 次后,回到首页,点击 “Take Heap Snapshot”,再抓取第二次快照,并停止录制。

4、在快照对比视图Comparison中,选择CompareTo Snapshot 1

5、查看对象新增销毁情况,优先关注:

• 操作次数的整数倍或整数倍+1( export 出的对象本身也有一条引用链);

• 业务对象,即 Constructor 的结构为包名/模块名/文件路径#泄漏对象

关键发现:

• 对比结果中,Proxy 对象数量异常,创建 70 个未销毁。

✅ 确认 Test 对象实例泄漏。

步骤3:追踪引用链

1、点击 “Shortest Paths” 获得如下 Proxy 对象实例的最短引用链,发现该 Proxy 对象的 Distance 为 1 。说明其为 GC Root 直接持有的对象,被 Native 侧直接持有未释放,即 JS 对象被 Local Handle / Global Handle 引用导致内存泄漏。

2、通过 Proxy 对象的 Distance 为 1 的 References ,确认内存泄漏是由 JS 对象被 Global Handle 引用导致。

步骤4:分析Local Handle / Global Handle类型持有导致泄漏问题

基于步骤3分析得到 Proxy 对象实例可能被 Local Handle / Global Handle 引用导致内存泄露,我们可以通过以下步骤继续分析定位:

1、配置Allocation录制模板并捕获数据

• 打开 DevEco Studio:确保你的工程已加载,并连接了目标设备或模拟器。

• 进入 Profiler 模块:在主界面下方菜单栏,找到并点击 Profiler 选项卡。

• 选择应用进程:运行应用,并在 “区域 2 ”选择目标设备和应用进程。

• 创建 Allocation 录制模板:选择 “Allocation” 并点击 Create Session 创建录制模板

配置录制参数

配置模式:选择详情模式(即关闭 Statistics Mode )。当前仅详情模式支持进行 ArkTS 和 Native 的关联分析。

配置开关:勾选“Local Handle”和“Global Handle”,这是关键配置。这将使Allocation 专门捕获与 JS-NAPI 句柄相关的内存分配事件。

如果底层镜像不支持该功能,则会提示“当前镜像版本不支持,请升级镜像”。

配置泳道范围:勾选 ArkTS Snapshot 泳道。这将使 Allocation 在录制结尾时自动抓取一份 Snapshot 快照用于关联分析。

启动录制:勾选了“Local Handle”开关后,如果是在应用本生命周期内首次录制local handle 数据,会触发弹窗请求重启应用以便录制对应信息,此时点击 OK 允许重启即可。

运行应用程序:运行目标应用,执行相关被怀疑引入内存泄露的业务操作,持续一段时间以增加内存压力和捕获更多数据。

停止录制:自动触发抓取一份 Snapshot 快照用于关联分析。点击快照,查找到疑似泄漏对象 Proxy 。

2、泄漏对象关联分析

定位可疑ArkTS对象:选中一个怀疑被泄漏的 ArkTS 对象实例(或对象类型),查看扩展标签页。

查看 Native List若某个 ArkTS 对象的 distance 值为 1,则可以通过扩展标签页中的 Native List 标签页,查看所有当前与该 JS 对象关联的 Native 句柄引用,以确认该 JS 对象是被 Local Handle 或 Global Handle 引用的对象。

关键信息:

(1)句柄类型:调用栈底层的符号 ArkGlobalHandle 或 ArkLocalHandle 判断泄漏类型

(2)调用栈:通过调用栈,可以定位到应用的 Native 代码(可能是 ArkUI 框架代码或你自己代码)中创建 napi_ref 的地方。

(3)注意点:

• 如果该 JS 对象节点不是一个被 Local Handle 或者 Global Handle 引用的对象,则会提示 "No Detail";

• 如果该 JS 对象确实是一个被 Local Handle 或者 Global Handle 引用的对象,但是对应的 native 内存的申请事件已经在此次录制之前完成内存分配,本次录制结果则无法展示对应的内存申请调用栈,需要重新录制,录制时需要注意将录制时执行的业务逻辑范围调整的尽量更早一些。

3、分析内存分配调用栈

• 排查调用栈:“Native List”标签页中的调用栈,找到对应业务代码

关键排查点:

• 检查是否在适当的时候调用了对应的句柄释放接口如 napi_delete_reference等。

• 梳理这段 Native 代码需要引用 ArkTS 对象的合理性,识别这个引用的生命周期是否过长,是否应该在某个条件满足后被释放;

• 对于 napi_ref ,其引用计数是关键。确保在不再需要引用时正确调用了 napi_delete_reference 。注意,引用计数可能因其他代码路径的创建或删除操作而意外增减。

检查句柄的作用域是否合理。local handle 是否应该只在 JS 执行上下文切换前使用?global handle 是否真的需要在整个应用生命周期都有效

修复验证

1、重新运行应用,再次使用 Memory 泳道监控。

2、重复多次进出消息中心页。

3、验证结果:

• 内存曲线恢复锯齿状,每次退出后回落至基线。

• 再次抓取快照对比,多次操作后业务对象实例数量无明显增长。

• 泄漏问题已修复。

体验与推广

DevEco Studio Profile 工具的跨语言交互内存泄漏定位能力已就绪,欢迎开发者前往 DevEco Studio 体验最新内存分析功能,助力开发者提高内存问题定位效率。

----------------------------------------------------------------------------------------------------------

🔗官网开发者学堂视频:华为开发者学堂

🔗社区DFX专题文章:华为开发者问答 | 华为开发者联盟

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

http://www.jsqmd.com/news/1306667/

相关文章:

  • Windows ADB驱动安装终极指南:3分钟一键解决Android连接问题
  • LCD1602 I2C转接模块应用指南:硬件简化与编程实践
  • 暗黑破坏神2终极高清补丁D2DX:三步安装教程与画质革命指南
  • 5分钟掌握OneMore:让OneNote文档排版效率提升300%的终极指南
  • 互联网医院牌照办理主要流程
  • Android日志精准捕获:基于PID过滤与实时输出的自动化脚本方案
  • 2026莆田有名的债务纠纷律师实用参考指南 - 谁都没有我好看
  • MIDAS GTS NX三维顶管下穿桥梁仿真分析全流程指南
  • 2026年义乌合同纠纷律师推荐:5位口碑与实力兼具的务实之选 - 本地品牌推荐
  • 基于事件触发分布式策略的孤岛微电网二次频率电压恢复控制研究(Simulink仿真实现)
  • 软件测试CNAS实验室评审,关键岗位人员自查清单
  • 2026国内定制数据线行业:三大核心趋势解析 - 全域品牌推荐
  • 自助服务终端条码扫描器选型方案:XT206H1成像解码与抗干扰技术解析
  • 游戏内存分析实战:子弹坐标定位与自动瞄准技术详解
  • 北京闲置爱马仕及时变现,零隐形扣费,高效盘活沉睡奢品资产 - 全国二奢机构参考
  • 10.1英寸电容触摸屏嵌入式集成实战:从驱动到Qt应用开发
  • AIO-3588SG 主板体验:88mm 见方塞进 RK3588S,6TOPS NPU + 32GB 内存的万能核心板
  • 宿舍多人共享随身WiFi性能对比:格行/波导/TCL/京东云 技术维度拆解
  • 蚂蚁InTech奖最后7天冲刺指南:技术评审逻辑与高效申报策略
  • BIM建模效率低?试试和AI工具配合使用
  • 2026年8月广东景楠照明灯饰太阳能庭院灯安装厂家地址整理|电话、时间与到店准备|2026年8月1日资料更新 - mobible
  • SubtitleEdit终极指南:免费开源字幕编辑工具全解析
  • 2026年08月 点胶机制造厂家供应厂家实力解析:东莞市世豪自动化设备有限公司等十家专业制造商综合观察 - 优企名品
  • Flutter在OpenHarmony上的图书详情页优化实践
  • 三步快速下载B站大会员4K视频和充电专属内容完整教程
  • 内置CO2传感器设计实战:从NDIR原理到硬件布局与故障排查
  • 2026库尔勒财务外包公司推荐|财务规划公司哪家好,嘉沃财税口碑实力派 - mobible
  • 三阶魔方七步还原法:从零基础到独立完成的完整指南
  • 2026年冷冻三黄鸡实力源头厂家观察:山东永和禽业有限公司全产业链解析 - 优企名品
  • 计算机毕业设计之宠物救助管理系统