1# JSVM-API 内存泄漏问题定位指导 2<!--Kit: NDK Development--> 3<!--Subsystem: arkcompiler--> 4<!--Owner: @yuanxiaogou; @string_sz--> 5<!--Designer: @knightaoko--> 6<!--Tester: @test_lzz--> 7<!--Adviser: @fang-jinxu--> 8 9JSVM的内存占用包括Native内存占用(C/C++侧的内存占用)和底层的JS引擎的堆内存占用,JS引擎会维护一个堆来管理其生成的JS对象,其生命周期由JS引擎维护,除此之外的内存我们归为Native内存。用户在使用JSVM时,可能碰到这两种内存异常增长的情况。 10 11本文先介绍如何定性分析,然后分两个部分介绍如何定位Native内存泄漏和JS引擎堆内存泄漏。 12 13## 定性分析 14 15可以通过hdc连接设备,执行如下命令行的方式对目标应用的内存进行采样,比较一段时间内的内存变化情况,从而定性分析是Native内存泄漏还是JS内存。下图中Pss Total列,native heap对应Native内存占用,AnnonPage other对应js堆内存占用。 16``` 17hidumper --mem $(pidof dest_app) 18``` 19<div align=left><img src="figures/jsvm_locate_memory_leak_hidump.png"/></div> 20 21 22## Native内存泄漏定位 23### 典型场景 241. OH_JSVM_CreateReference 和 OH_JSVM_DeleteReference 接口没有成对调用,导致Reference没有被释放。 25```c++ 26JSVM_Value obj = nullptr; 27OH_JSVM_CreateObject(env, &obj); 28// 创建引用 29JSVM_Ref reference; 30OH_JSVM_CreateReference(env, obj, 1, &reference); 31 32// 使用引用 33JSVM_Value result; 34OH_JSVM_GetReferenceValue(env, reference, &result); 35 36// 未释放引用 37// OH_JSVM_DeleteReference(env, reference); 38``` 39 40### 定位步骤 41为了分析Native内存泄漏,可以借助DevEco Studio的内存分析模块,具体参考文档:[内存分析及优化](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-insight-session-allocations-memory)。 421. 使用Profiler的Allocation模块记录一段时间内的Native内存信息。 43<div align=left><img src="figures/jsvm_locate_memory_leak_allocation1.png"/></div> 44 452. 比较这段时间内"Created & Existing"的内存变化情况,如果存在占比较大且Count较大的未释放内存,则怀疑存在内存泄漏,展开进一步查看调用栈。 46<div align=left><img src="figures/jsvm_locate_memory_leak_allocation2.png"/></div> 47 48 49## JS引擎堆内存泄漏定位 50### 典型场景 511. 全局变量滥用,导致dom元素未释放。 52```js 53const elements = []; 54function createElements() { 55 for (let i = 0; i < 1000; i++) { 56 const el = document.createElement('div'); 57 document.body.appendChild(el); 58 elements.push(el); // 即使从 DOM 移除,数组仍保留引用 59 } 60} 61``` 62 63### 定位步骤 64JSVM目前提供了OH_JSVM_OpenInspector开启inspector,参考[使用OH_JSVM_OpenInspector](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/jsvm-debugger-cpuprofiler-heapsnapshot#%E4%BD%BF%E7%94%A8-oh_jsvm_openinspector),在此基础上可以[使用 Chrome inspect 页面进行调试](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/jsvm-debugger-cpuprofiler-heapsnapshot#%E4%BD%BF%E7%94%A8-chrome-inspect-%E9%A1%B5%E9%9D%A2%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95)。 65通过使用DevTools工具,对目标场景内的堆内存进行快照(快照前先点击上方的垃圾回收按钮进行垃圾回收),利用快照对比功能,找到未释放的JS对象和其所在源码中的位置,进一步指导定位堆内存未释放的原因。 66<div align=left><img src="figures/jsvm_locate_memory_leak_devtool.png"/></div>