JSLeakWatcher特性指导

0 评论 134 浏览 0 收藏 11 分钟

在ArkTS开发中,若一个ArkTS对象不再需要,但仍被某个引用链“意外”持有,则垃圾回收器无法回收该内存,从而导致内存泄漏。

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

JSLeakWatcher特性指导-华为开发者话题 | 华为开发者联盟

1、概述

1.1 背景

在ArkTS开发中,若一个ArkTS对象不再需要,但仍被某个引用链“意外”持有,则垃圾回收器无法回收该内存,从而导致内存泄漏。

ArkTS对象内存泄漏,通常会带来以下影响:

1、性能:若应用占用内存持续增长,系统为释放内存会频繁触发GC,而GC执行时会暂停应用主线程(Stop-The-World机制),导致界面卡顿、滑动不流畅;长期泄漏同时也会让内存碎片化严重,系统分配/释放内存效率降低,进一步拖慢应用运行速度,发生响应变慢等问题;

2、内存:若应用泄漏内存持续积累并达到ArkTS Local堆/共享堆或进程的OOM的上限阈值时,则会产生JS Crash;

3、功耗:系统频繁GC会消耗大量CPU资源,持续高占用会导致设备发热,加速电量消耗;

4、功能:部分泄漏会因对象引用残留间接导致功能异常(如ArkUI组件状态错乱、资源冲突、回调重复执行等)。

1.2 JSLeakWatcher介绍

为帮助开发人员快速定位ArkTS对象内存泄漏问题,HarmonyOS提供了ArkTS内存泄漏检测能力JSLeakWatcher,开发者可轻松接入相关API,实现对系统内具有生命周期的ArkTS组件对象定期执行泄漏自检测。

当检测到ArkTS对象有内存泄漏时,JSLeakWatcher会生成泄漏信息文件(包括*.rawheap文件和*.jsleaklist文件,详细参考2.4),将这两个文件导入IDE(DevEco Studio 6.0.0起均支持),就可以获取泄露对象列表。通过泄漏对象列表中的泄漏对象直接跳转到引用链,加速找到持有该泄漏对象的根GC_ROOT,提升泄漏问题闭环效率,降低定界定位成本。对于自定义组件和Ability组件对象,JSLeakWatcher可以直接关联到业务代码信息,XComponent组件、NodeContainer组件、Window组件不支持关联到业务代码信息。

2、实现原理

2.1 原理描述

JSLeakWatcher提供了清晰、易用的ArkTS接口,主要功能如下:

1、定期对目标应用执行一次垃圾回收操作(FullGC),尝试回收当前所有根不可达的ArkTS对象(未被GC_ROOT对象持有的ArkTS对象);

2、当执行完垃圾回收操作后,若框架检测到仍有未被回收的ArkTS对象,则立即生成此刻的ArkTS堆快照(*.rawheap)文件及泄漏对象列表(*.jsleaklist)文件,并存放在应用沙箱内。ArkTS对象发生内存泄漏,通常是因为对象在生命周期结束后仍未被解除引用,导致垃圾回收器(GC)无法识别并将其回收。常见原因包括:

(1)Native层强引用该对象:在Node-API中对ArkTS对象创建了持久化强引用。(Node-API介绍参考Node-API简介;创建和销毁强引用方式参考napi_create_reference、napi_delete_reference);

(2)闭包捕获:内部函数持有对外部作用域ArkTS对象的引用,即使外部作用域已退出;

(3)全局或模块级缓存:使用Map、Array缓存长期持有ArkTS对象。

2.2 泄漏检测流程

1、应用在启动后调用enableLeakWatcher()接口开启ArkTS泄漏检测功能。

2、检测流程:

(1)通过FinalizationRegistry机制,注册监控组件对象的GC回调函数,同时注册销毁回调函数。说明:FinalizationRegistry是JavaScript提供的弱引用监听机制,当注册的对象被垃圾回收时,会自动触发预设的回调函数;

(2)当组件对象被销毁时,销毁的回调函数会将对象记录在list1中,这些被销毁,同时记录在list1中的对象应该在GC后被清除掉;

(3)被销毁的组件在被GC时(周期性执行,默认90秒),GC的回调函数会将该对象记录在list2中,记录在list2中的对象被成功GC掉;

(4)list1-list2就是泄漏对象;

(5)list1-list2如果不为空,则说明存在泄漏:GC后延迟一段时间(默认5秒),异步dump ArkTS堆快照生成*.rawheap文件,然后根据list1-list2对象数组,生成*.jsleaklist文件,最后将*.rawheap文件和*.jsleaklist文件落盘在应用沙箱中;

(6)通过将*.rawheap文件和*.jsleaklist文件导出到IDE中,即可以获取泄漏对象的详细信息。

3、应用在退出时调用enableLeakWatcher接口关闭ArkTS泄漏检测功能。

2.3 关键能力

截止7.0版本(API 26.0.0),JSLeakWatcher支持以下关键能力(含配置):

1、组件相关

(1)支持监控五大类型组件,包括:NodeContainer、Ability、Window、XComponent、CustomComponent。

(2)支持指定要检测的对象变量名,只监控相关对象是否存在泄漏;

(3)支持指定要检测的组件类型名,只监控相关类型下面所有的对象是否存在泄漏;

(4)支持指定要检测的自定义组件id名单,只监控相关id的对象是否存在泄漏;

(5)支持指定不检测的自定义组件类名、Abilty类名和Window窗口名名单,传入自定义组件类名、Abilty类名和Window窗口名名单,不监控相关对象是否存在泄漏;

2、调用机制

(1)插桩调用:支持在业务代码中调用接口使用;

(2)测试环境新增支持应用免插桩调用(通过将系统参数“hiviewdfx.hichecker.jsleakwatcher.leak.check”设置为“enable.应用名”),相关配置使用默认值,发生泄漏后,上报系统事件,最后在Deveco Testing(从7.0.0.200版本开始支持)呈现泄漏内容。

3、dump机制

(1)支持异步dump快照;

(2)支持自定义配置dump触发条件(应用在前台/后台泄漏个数为多少时执行dump);

(3)支持配置最大dump个数,默认10份快照文件,超过后会老化;

(3)支持配置GC后多久执行快照dump,默认是5秒;

4、快照生成和老化机制

(1)只要有泄漏被检测到,就会新dump一份快照并生成一个泄漏列表文件(新文件生成之前,同一生命周期内生成的老的快照文件和泄漏列表文件都会被删除)。文件生成完之后,会通过回调告知应用快照文件路径和泄露列表文件路径;

(2)应用沙箱内文件上限默认是20个,超过20个文件会被老化。

5、检测间隔

(1)支持配置每轮检测间隔时间,默认且最小为90秒。如果用户设置的时间小于90秒,将不会生效。注意,GC属于高开销操作,会导致应用卡顿,因此建议开发者根据实际情况调大检测间隔,减轻卡顿频率。

2.4 生成文件介绍

1、*.rawheap文件

记录了抓快照时所有无法被回收的ArkTS对象信息,包括泄漏对象和GC_ROOT可达对象。快照内容包括ArkTS对象的节点属性与引用链,包括对象类型、涉及的代码行等。

2、*.jsleaklist文件

统计无法回收的ArkTS泄漏对象列表,导入到IDE可以和rawheap中的ArkTS对象通过ID进行匹配,查看ArkTS对象中的各属性。

3、开发实践

见官方文档:https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-js-leak-watcher 

4、接口说明

见官方文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-jsleakwatcher 

本文由 @华为开发者联盟 授权发布于人人都是产品经理。未经作者许可,禁止转载

题图来自Unsplash,基于CC0协议

该文观点仅代表作者本人,人人都是产品经理平台仅提供信息存储空间服务

更多精彩内容,请关注人人都是产品经理微信公众号或下载App
评论
评论请登录
  1. 目前还没评论,等你发挥!