1e41f4b71Sopenharmony_ci# JSVM-API调试&定位
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ciJSVM,既标准JS引擎,是严格遵守Ecmascript规范的JavaScript代码执行引擎。 详情参考:[JSVM](../reference/common/_j_s_v_m.md)。
4e41f4b71Sopenharmony_ci基于JSVM的JS代码调试调优能力包括:Debugger、CPU Profiler、Heap Snapshot、Heap Statistics。涉及以下接口:
5e41f4b71Sopenharmony_ci| 接口名  |  接口功能 |
6e41f4b71Sopenharmony_ci|---|---|
7e41f4b71Sopenharmony_ci| OH_JSVM_GetVM  |  将检索给定环境的虚拟机实例。 |
8e41f4b71Sopenharmony_ci| OH_JSVM_GetHeapStatistics  |  返回一组虚拟机堆的统计数据。 |
9e41f4b71Sopenharmony_ci| OH_JSVM_StartCpuProfiler  |  创建并启动一个CPU profiler。 |
10e41f4b71Sopenharmony_ci| OH_JSVM_StopCpuProfiler  |  停止CPU profiler并将结果输出到流。 |
11e41f4b71Sopenharmony_ci| OH_JSVM_TakeHeapSnapshot  |  获取当前堆快照并将其输出到流。 |
12e41f4b71Sopenharmony_ci| OH_JSVM_OpenInspector  |  在指定的主机和端口上激活inspector,将用来调试JS代码。 |
13e41f4b71Sopenharmony_ci| OH_JSVM_OpenInspectorWithName | 基于传入的 pid 和 name 激活 inspector |
14e41f4b71Sopenharmony_ci| OH_JSVM_CloseInspector  |  尝试关闭剩余的所有inspector连接。 |
15e41f4b71Sopenharmony_ci| OH_JSVM_WaitForDebugger  |  等待主机与inspector建立socket连接,连接建立后程序将继续运行。发送Runtime.runIfWaitingForDebugger命令。 |
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ci本文将介绍调试、CPU Profiler、Heap Snapshot的使用方法。
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci## 调试能力使用方法
21e41f4b71Sopenharmony_ci
22e41f4b71Sopenharmony_ci### 使用 OH_JSVM_OpenInspector
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci1. 在应用工程配置文件module.json中配置网络权限:
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci```
27e41f4b71Sopenharmony_ci"requestPermissions": [{
28e41f4b71Sopenharmony_ci  "name": "ohos.permission.INTERNET",
29e41f4b71Sopenharmony_ci  "reason": "$string:app_name",
30e41f4b71Sopenharmony_ci  "usedScene": {
31e41f4b71Sopenharmony_ci    "abilities": [
32e41f4b71Sopenharmony_ci      "FromAbility"
33e41f4b71Sopenharmony_ci    ],
34e41f4b71Sopenharmony_ci    "when": "inuse"
35e41f4b71Sopenharmony_ci  }
36e41f4b71Sopenharmony_ci}]
37e41f4b71Sopenharmony_ci```
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci2. 为避免debugger过程中的暂停被误报为无响应异常,可以[开启DevEco Studio的Debug模式](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-debug-arkts-debug-V5)(无需设置断点),或者可以在非主线程的其他线程中运行JSVM。
40e41f4b71Sopenharmony_ci3. 在执行JS代码之前,调用OH_JSVM_OpenInspector在指定的主机和端口上激活inspector,创建socket。例如OH_JSVM_OpenInspector(env, "localhost", 9225),在端侧本机端口9225创建socket。
41e41f4b71Sopenharmony_ci4. 调用OH_JSVM_WaitForDebugger,等待建立socket连接。
42e41f4b71Sopenharmony_ci5. 检查端侧端口是否打开成功。hdc shell "netstat -anp | grep 9225"。结果为9225端口状态为“LISTEN"即可。
43e41f4b71Sopenharmony_ci6. 转发端口。hdc fport tcp:9229 tcp:9225。转发PC侧端口9229到端侧端口9225。结果为"Forwardport result:OK"即可。
44e41f4b71Sopenharmony_ci7. 在chrome浏览器地址栏输入"localhost:9229/json",回车。获取端口连接信息。拷贝"devtoolsFrontendUrl"字段url内容到地址栏,回车,进入DevTools源码页,将看到在应用中通过OH_JSVM_RunScript执行的JS源码,此时暂停在第一行JS源码处。
45e41f4b71Sopenharmony_ci8. 用户可在源码页打断点,通过按钮发出各种调试命令控制JS代码执行,并查看变量。
46e41f4b71Sopenharmony_ci9. 调用OH_JSVM_CloseInspector关闭inspector,结束socket连接。
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ci#### 示例代码
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ci```cpp
51e41f4b71Sopenharmony_ci#include "ark_runtime/jsvm.h"
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ci#include <string>
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ciusing namespace std;
56e41f4b71Sopenharmony_ci
57e41f4b71Sopenharmony_ci// 待调试的JS源码
58e41f4b71Sopenharmony_cistatic string srcDebugger = R"JS(
59e41f4b71Sopenharmony_ciconst concat = (...args) => args.reduce((a, b) => a + b);
60e41f4b71Sopenharmony_civar dialogue = concat('"What ', 'is ', 'your ', 'name ', '?"');
61e41f4b71Sopenharmony_cidialogue = concat(dialogue, ' --', '"My ', 'name ', 'is ', 'Bob ', '."');
62e41f4b71Sopenharmony_ci)JS";
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ci// 开启debugger
65e41f4b71Sopenharmony_cistatic void EnableInspector(JSVM_Env env) {
66e41f4b71Sopenharmony_ci    // 在指定的主机和端口上激活inspector,创建socket。
67e41f4b71Sopenharmony_ci    OH_JSVM_OpenInspector(env, "localhost", 9225);
68e41f4b71Sopenharmony_ci    // 等待建立socket连接。
69e41f4b71Sopenharmony_ci    OH_JSVM_WaitForDebugger(env, true);
70e41f4b71Sopenharmony_ci}
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci// 关闭debugger
73e41f4b71Sopenharmony_cistatic void CloseInspector(JSVM_Env env) {
74e41f4b71Sopenharmony_ci    // 关闭inspector,结束socket连接。
75e41f4b71Sopenharmony_ci    OH_JSVM_CloseInspector(env);
76e41f4b71Sopenharmony_ci}
77e41f4b71Sopenharmony_ci
78e41f4b71Sopenharmony_cistatic void RunScript(JSVM_Env env) {
79e41f4b71Sopenharmony_ci    JSVM_HandleScope handleScope;
80e41f4b71Sopenharmony_ci    OH_JSVM_OpenHandleScope(env, &handleScope);
81e41f4b71Sopenharmony_ci
82e41f4b71Sopenharmony_ci    JSVM_Value jsSrc;
83e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, srcDebugger.c_str(), srcDebugger.size(), &jsSrc);
84e41f4b71Sopenharmony_ci
85e41f4b71Sopenharmony_ci    JSVM_Script script;
86e41f4b71Sopenharmony_ci    OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script);
87e41f4b71Sopenharmony_ci
88e41f4b71Sopenharmony_ci    JSVM_Value result;
89e41f4b71Sopenharmony_ci    OH_JSVM_RunScript(env, script, &result);
90e41f4b71Sopenharmony_ci
91e41f4b71Sopenharmony_ci    OH_JSVM_CloseHandleScope(env, handleScope);
92e41f4b71Sopenharmony_ci}
93e41f4b71Sopenharmony_ci
94e41f4b71Sopenharmony_civoid RunDemo() {
95e41f4b71Sopenharmony_ci    JSVM_InitOptions initOptions{};
96e41f4b71Sopenharmony_ci    OH_JSVM_Init(&initOptions);
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci    JSVM_VM vm;
99e41f4b71Sopenharmony_ci    OH_JSVM_CreateVM(nullptr, &vm);
100e41f4b71Sopenharmony_ci    JSVM_VMScope vmScope;
101e41f4b71Sopenharmony_ci    OH_JSVM_OpenVMScope(vm, &vmScope);
102e41f4b71Sopenharmony_ci
103e41f4b71Sopenharmony_ci    JSVM_Env env;
104e41f4b71Sopenharmony_ci    OH_JSVM_CreateEnv(vm, 0, nullptr, &env);
105e41f4b71Sopenharmony_ci    // 执行JS代码之前打开debugger。
106e41f4b71Sopenharmony_ci    EnableInspector(env);
107e41f4b71Sopenharmony_ci    JSVM_EnvScope envScope;
108e41f4b71Sopenharmony_ci    OH_JSVM_OpenEnvScope(env, &envScope);
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ci    // 执行JS代码。
111e41f4b71Sopenharmony_ci    RunScript(env);
112e41f4b71Sopenharmony_ci
113e41f4b71Sopenharmony_ci    OH_JSVM_CloseEnvScope(env, envScope);
114e41f4b71Sopenharmony_ci    // 执行JS代码之后关闭debugger。
115e41f4b71Sopenharmony_ci    CloseInspector(env);
116e41f4b71Sopenharmony_ci    OH_JSVM_DestroyEnv(env);
117e41f4b71Sopenharmony_ci    OH_JSVM_CloseVMScope(vm, vmScope);
118e41f4b71Sopenharmony_ci    OH_JSVM_DestroyVM(vm);
119e41f4b71Sopenharmony_ci}
120e41f4b71Sopenharmony_ci```
121e41f4b71Sopenharmony_ci
122e41f4b71Sopenharmony_ci### 使用 OH_JSVM_OpenInspectorWithName
123e41f4b71Sopenharmony_ci
124e41f4b71Sopenharmony_ci1. 在应用工程配置文件module.json中配置网络权限:
125e41f4b71Sopenharmony_ci
126e41f4b71Sopenharmony_ci```
127e41f4b71Sopenharmony_ci"requestPermissions": [{
128e41f4b71Sopenharmony_ci  "name": "ohos.permission.INTERNET",
129e41f4b71Sopenharmony_ci  "reason": "$string:app_name",
130e41f4b71Sopenharmony_ci  "usedScene": {
131e41f4b71Sopenharmony_ci    "abilities": [
132e41f4b71Sopenharmony_ci      "FromAbility"
133e41f4b71Sopenharmony_ci    ],
134e41f4b71Sopenharmony_ci    "when": "inuse"
135e41f4b71Sopenharmony_ci  }
136e41f4b71Sopenharmony_ci}]
137e41f4b71Sopenharmony_ci```
138e41f4b71Sopenharmony_ci
139e41f4b71Sopenharmony_ci2. 为避免debugger过程中的暂停被误报为无响应异常,可以[开启DevEco Studio的Debug模式](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-debug-arkts-debug-V5)(无需设置断点),或者可以在非主线程的其他线程中运行JSVM。
140e41f4b71Sopenharmony_ci3. 打开 inspector 端口, 链接 devtools 用于调试, 其流程如下:  在执行JS代码之前,调用OH_JSVM_OpenInspector在指定的主机和端口上激活inspector,创建socket。例如OH_JSVM_OpenInspectorWithName(env, 123, “test”),创建 tcp socket 及其对应的 unixdomain 端口
141e41f4b71Sopenharmony_ci4. 调用OH_JSVM_WaitForDebugger,等待建立socket连接。
142e41f4b71Sopenharmony_ci5. 检查端侧端口是否打开成功。hdc shell "cat /proc/net/unix | grep jsvm"。结果出现可用的 unix 端口即可, 如: jsvm_devtools_remote_9229_123, 其中 9229 为 tcp 端口号, 123 为对应的 pid
143e41f4b71Sopenharmony_ci6. 转发端口。hdc fport tcp:9229 tcp:9229。转发PC侧端口9229到端侧端口9229。结果为"Forwardport result:OK"即可。
144e41f4b71Sopenharmony_ci7. 在 chrome 浏览器地址栏输入 "localhost:9229/json",回车。获取端口连接信息。打开Chrome开发者工具,拷贝"devtoolsFrontendUrl"字段url内容到地址栏,回车,进入DevTools源码页,将看到在应用中通过OH_JSVM_RunScript执行的JS源码,此时暂停在第一行JS源码处。
145e41f4b71Sopenharmony_ci8. 用户可在源码页打断点,通过按钮发出各种调试命令控制JS代码执行,并查看变量。
146e41f4b71Sopenharmony_ci9. 调用OH_JSVM_CloseInspector关闭inspector,结束socket连接。
147e41f4b71Sopenharmony_ci
148e41f4b71Sopenharmony_ci#### 代码示例
149e41f4b71Sopenharmony_ci
150e41f4b71Sopenharmony_ci对应的 enable inspector 替换为下面的即可
151e41f4b71Sopenharmony_ci```cpp
152e41f4b71Sopenharmony_ci// 开启debugger
153e41f4b71Sopenharmony_cistatic void EnableInspector(JSVM_Env env) {
154e41f4b71Sopenharmony_ci    // 在指定的主机和端口上激活inspector,创建socket。
155e41f4b71Sopenharmony_ci    OH_JSVM_OpenInspectorWithName(env, 123, "test");
156e41f4b71Sopenharmony_ci    // 等待建立socket连接。
157e41f4b71Sopenharmony_ci    OH_JSVM_WaitForDebugger(env, true);
158e41f4b71Sopenharmony_ci}
159e41f4b71Sopenharmony_ci```
160e41f4b71Sopenharmony_ci
161e41f4b71Sopenharmony_ci## CPU Profiler及Heap Snapshot使用方法
162e41f4b71Sopenharmony_ci
163e41f4b71Sopenharmony_ci### CPU Profiler接口使用方法
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ci1. 在执行JS代码之前,调用OH_JSVM_StartCpuProfiler开始采样并返回JSVM_CpuProfiler。
166e41f4b71Sopenharmony_ci2. 在执行JS代码后,调用OH_JSVM_StopCpuProfiler,传入1中返回的JSVM_CpuProfiler,传入输出流回调及输出流指针。数据将会写入指定的输出流中。
167e41f4b71Sopenharmony_ci3. 输出数据为JSON字符串。可存入.cpuprofile文件中。该文件类型可导入Chrome浏览器-DevTools-JavaScript Profiler工具中解析成性能分析视图。
168e41f4b71Sopenharmony_ci
169e41f4b71Sopenharmony_ci### Heap Snapshot接口使用方法
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci1.为分析某段JS代码的堆对象创建情况。可在执行JS代码前后,分别调用一次OH_JSVM_TakeHeapSnapshot。传入输出流回调及输出流指针。数据将会写入指定的输出流中。
172e41f4b71Sopenharmony_ci2.输出数据可存入.heapsnapshot文件中。该文件类型可导入Chrome浏览器-DevTools-Memory工具中解析成内存分析视图。
173e41f4b71Sopenharmony_ci
174e41f4b71Sopenharmony_ci### 示例代码
175e41f4b71Sopenharmony_ci
176e41f4b71Sopenharmony_ci```cpp
177e41f4b71Sopenharmony_ci#include "ark_runtime/jsvm.h"
178e41f4b71Sopenharmony_ci
179e41f4b71Sopenharmony_ci#include <fstream>
180e41f4b71Sopenharmony_ci#include <iostream>
181e41f4b71Sopenharmony_ci
182e41f4b71Sopenharmony_ciusing namespace std;
183e41f4b71Sopenharmony_ci
184e41f4b71Sopenharmony_ci// 待调优的JS代码。
185e41f4b71Sopenharmony_cistatic string srcProf = R"JS(
186e41f4b71Sopenharmony_cifunction sleep(delay) {
187e41f4b71Sopenharmony_ci    var start = (new Date()).getTime();
188e41f4b71Sopenharmony_ci    while ((new Date()).getTime() - start < delay) {
189e41f4b71Sopenharmony_ci        continue;
190e41f4b71Sopenharmony_ci    }
191e41f4b71Sopenharmony_ci}
192e41f4b71Sopenharmony_ci
193e41f4b71Sopenharmony_cifunction work3() {
194e41f4b71Sopenharmony_ci    sleep(300);
195e41f4b71Sopenharmony_ci}
196e41f4b71Sopenharmony_ci
197e41f4b71Sopenharmony_cifunction work2() {
198e41f4b71Sopenharmony_ci    work3();
199e41f4b71Sopenharmony_ci    sleep(200);
200e41f4b71Sopenharmony_ci}
201e41f4b71Sopenharmony_ci
202e41f4b71Sopenharmony_cifunction work1() {
203e41f4b71Sopenharmony_ci    work2();
204e41f4b71Sopenharmony_ci    sleep(100);
205e41f4b71Sopenharmony_ci}
206e41f4b71Sopenharmony_ci
207e41f4b71Sopenharmony_ciwork1();
208e41f4b71Sopenharmony_ci)JS";
209e41f4b71Sopenharmony_ci
210e41f4b71Sopenharmony_ci// 数据输出流回调,用户自定义,处理返回的调优数据,此处以写入文件为例。
211e41f4b71Sopenharmony_cistatic bool OutputStream(const char *data, int size, void *streamData) {
212e41f4b71Sopenharmony_ci    auto &os = *reinterpret_cast<ofstream *>(streamData);
213e41f4b71Sopenharmony_ci    if (data) {
214e41f4b71Sopenharmony_ci        os.write(data, size);
215e41f4b71Sopenharmony_ci    } else {
216e41f4b71Sopenharmony_ci        os.close();
217e41f4b71Sopenharmony_ci    }
218e41f4b71Sopenharmony_ci    return true;
219e41f4b71Sopenharmony_ci}
220e41f4b71Sopenharmony_ci
221e41f4b71Sopenharmony_cistatic JSVM_CpuProfiler ProfilingBegin(JSVM_VM vm) {
222e41f4b71Sopenharmony_ci    // 文件输出流,保存调优数据,/data/storage/el2/base/files为沙箱路径。以包名为com.example.helloworld为例。
223e41f4b71Sopenharmony_ci    // 实际文件会保存到/data/app/el2/100/base/com.example.helloworld/files/heap-snapshot-begin.heapsnapshot224e41f4b71Sopenharmony_ci    ofstream heapSnapshot("/data/storage/el2/base/files/heap-snapshot-begin.heapsnapshot",
225e41f4b71Sopenharmony_ci                          ios::out | ios:: binary | ios::trunc);
226e41f4b71Sopenharmony_ci    // 执行JS前获取一次Heap Snapshot数据。
227e41f4b71Sopenharmony_ci    OH_JSVM_TakeHeapSnapshot(vm, OutputStream, &heapSnapshot);
228e41f4b71Sopenharmony_ci    JSVM_CpuProfiler cpuProfiler;
229e41f4b71Sopenharmony_ci    // 开启CPU Profiler。
230e41f4b71Sopenharmony_ci    OH_JSVM_StartCpuProfiler(vm, &cpuProfiler);
231e41f4b71Sopenharmony_ci    return cpuProfiler;
232e41f4b71Sopenharmony_ci}
233e41f4b71Sopenharmony_ci
234e41f4b71Sopenharmony_ci// 关闭调优数据采集工具
235e41f4b71Sopenharmony_cistatic void ProfilingEnd(JSVM_VM vm, JSVM_CpuProfiler cpuProfiler) {
236e41f4b71Sopenharmony_ci    // 文件输出流,保存调优数据,/data/storage/el2/base/files为沙箱路径。以包名为com.example.helloworld为例。
237e41f4b71Sopenharmony_ci    // 实际文件会保存到/data/app/el2/100/base/com.example.helloworld/files/cpu-profile.cpuprofile238e41f4b71Sopenharmony_ci    ofstream cpuProfile("/data/storage/el2/base/files/cpu-profile.cpuprofile",
239e41f4b71Sopenharmony_ci                        ios::out | ios:: binary | ios::trunc);
240e41f4b71Sopenharmony_ci    // 关闭CPU Profiler,获取数据。
241e41f4b71Sopenharmony_ci    OH_JSVM_StopCpuProfiler(vm, cpuProfiler, OutputStream, &cpuProfile);
242e41f4b71Sopenharmony_ci    ofstream heapSnapshot("/data/storage/el2/base/files/heap-snapshot-end.heapsnapshot",
243e41f4b71Sopenharmony_ci                              ios::out | ios:: binary | ios::trunc);
244e41f4b71Sopenharmony_ci    // 执行JS后再获取一次Heap Snapshot数据,与执行前数据作对比,以分析内存问题或者进行内存调优。
245e41f4b71Sopenharmony_ci    OH_JSVM_TakeHeapSnapshot(vm, OutputStream, &heapSnapshot);
246e41f4b71Sopenharmony_ci}
247e41f4b71Sopenharmony_ci
248e41f4b71Sopenharmony_cistatic void RunScriptWithStatistics(JSVM_Env env) {
249e41f4b71Sopenharmony_ci    JSVM_VM vm;
250e41f4b71Sopenharmony_ci    OH_JSVM_GetVM(env, &vm);
251e41f4b71Sopenharmony_ci
252e41f4b71Sopenharmony_ci    // 开始调优。
253e41f4b71Sopenharmony_ci    auto cpuProfiler = ProfilingBegin(vm);
254e41f4b71Sopenharmony_ci
255e41f4b71Sopenharmony_ci    JSVM_HandleScope handleScope;
256e41f4b71Sopenharmony_ci    OH_JSVM_OpenHandleScope(env, &handleScope);
257e41f4b71Sopenharmony_ci
258e41f4b71Sopenharmony_ci    JSVM_Value jsSrc;
259e41f4b71Sopenharmony_ci    OH_JSVM_CreateStringUtf8(env, srcProf.c_str(), srcProf.size(), &jsSrc);
260e41f4b71Sopenharmony_ci
261e41f4b71Sopenharmony_ci    JSVM_Script script;
262e41f4b71Sopenharmony_ci    OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script);
263e41f4b71Sopenharmony_ci
264e41f4b71Sopenharmony_ci    JSVM_Value result;
265e41f4b71Sopenharmony_ci    // 执行JS代码。
266e41f4b71Sopenharmony_ci    OH_JSVM_RunScript(env, script, &result);
267e41f4b71Sopenharmony_ci
268e41f4b71Sopenharmony_ci    OH_JSVM_CloseHandleScope(env, handleScope);
269e41f4b71Sopenharmony_ci
270e41f4b71Sopenharmony_ci    // 结束调优。
271e41f4b71Sopenharmony_ci    ProfilingEnd(vm, cpuProfiler);
272e41f4b71Sopenharmony_ci}
273e41f4b71Sopenharmony_ci
274e41f4b71Sopenharmony_civoid RunDemo() {
275e41f4b71Sopenharmony_ci    JSVM_InitOptions initOptions{};
276e41f4b71Sopenharmony_ci    OH_JSVM_Init(&initOptions);
277e41f4b71Sopenharmony_ci
278e41f4b71Sopenharmony_ci    JSVM_VM vm;
279e41f4b71Sopenharmony_ci    OH_JSVM_CreateVM(nullptr, &vm);
280e41f4b71Sopenharmony_ci    JSVM_VMScope vmScope;
281e41f4b71Sopenharmony_ci    OH_JSVM_OpenVMScope(vm, &vmScope);
282e41f4b71Sopenharmony_ci
283e41f4b71Sopenharmony_ci    JSVM_Env env;
284e41f4b71Sopenharmony_ci    OH_JSVM_CreateEnv(vm, 0, nullptr, &env);
285e41f4b71Sopenharmony_ci    JSVM_EnvScope envScope;
286e41f4b71Sopenharmony_ci    OH_JSVM_OpenEnvScope(env, &envScope);
287e41f4b71Sopenharmony_ci
288e41f4b71Sopenharmony_ci    RunScriptWithStatistics(env);
289e41f4b71Sopenharmony_ci
290e41f4b71Sopenharmony_ci    OH_JSVM_CloseEnvScope(env, envScope);
291e41f4b71Sopenharmony_ci    OH_JSVM_DestroyEnv(env);
292e41f4b71Sopenharmony_ci    OH_JSVM_CloseVMScope(vm, vmScope);
293e41f4b71Sopenharmony_ci    OH_JSVM_DestroyVM(vm);
294e41f4b71Sopenharmony_ci}
295e41f4b71Sopenharmony_ci```
296