使用JSVM-API接口进行JavaScript代码调试调优
==============================

#### 简介

这些JSVM-API接口涵盖了虚拟机实例检索、内存分析、性能剖析和调试支持，为优化代码性能及提升开发效率提供了有力的支持。

#### 基本概念

*   **JSVM**：JavaScript虚拟机是执行JavaScript代码的环境。它负责解析和执行JavaScript代码，管理内存，并提供与其他系统资源的交互。接口如OH\_JSVM\_GetVM用于检索特定环境的虚拟机实例，这是JSVM管理的基本操作之一。
*   **调试（debug）**：调试是程序开发中的一项重要活动，它涉及到定位、分析和修复代码中的错误。OH\_JSVM\_OpenInspector和OH\_JSVM\_CloseInspector接口提供了在特定主机和端口上激活和关闭inspector的功能，inspector是一个用于调试JavaScript代码的工具，允许开发者实时查看和交互程序的运行状态。

#### 接口说明

| 接口 | 功能说明 |
| :-- | :-- |
| OH\_JSVM\_GetVM | 将检索给定环境的虚拟机实例。 |
| OH\_JSVM\_GetHeapStatistics | 返回一组虚拟机堆的统计数据。 |
| OH\_JSVM\_StartCpuProfiler | 创建并启动一个CPU profiler。 |
| OH\_JSVM\_StopCpuProfiler | 停止CPU profiler并将结果输出到流。 |
| OH\_JSVM\_TakeHeapSnapshot | 获取当前堆快照并将其输出到流。 |
| OH\_JSVM\_OpenInspector | 在指定的主机和端口上激活inspector，将用来调试JS代码。 |
| OH\_JSVM\_OpenInspectorWithName | 基于传入的 pid 和 name 激活 inspector。 |
| OH\_JSVM\_CloseInspector | 尝试关闭剩余的所有inspector连接。 |
| OH\_JSVM\_WaitForDebugger | 等待主机与inspector建立socket连接，连接建立后程序将继续运行。发送Runtime.runIfWaitingForDebugger命令。 |

#### 使用示例

JSVM-API接口开发流程参考[使用JSVM-API实现JS与C/C++语言交互开发流程](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-jsvm-process)，本文仅展示接口对应的C++代码。

#### \[h2\]OH\_JSVM\_GetVM

检索给定环境中的虚拟机实例。

cpp部分代码

// hello.cpp
#include "napi/native\_api.h"
#include "ark\_runtime/jsvm.h"
#include <hilog/log.h>

// OH\_JSVM\_GetVM的样例方法
static JSVM\_Value GetVM(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    // 获取当前虚拟机对象,后续可以进行与虚拟机相关的操作或分析
    JSVM\_VM testVm;
    JSVM\_Status status = OH\_JSVM\_GetVM(env, &testVm);
    JSVM\_Value result = nullptr;
    if (status != JSVM\_OK || testVm == nullptr) {
        OH\_LOG\_ERROR(LOG\_APP, "JSVM OH\_JSVM\_GetVM: failed");
        OH\_JSVM\_GetBoolean(env, true, &result);
    } else {
        OH\_LOG\_INFO(LOG\_APP, "JSVM OH\_JSVM\_GetVM: success");
        OH\_JSVM\_GetBoolean(env, false, &result);
    }
    return result;
}
// GetVM注册回调
static JSVM\_CallbackStruct param\[\] = {
    {.data = nullptr, .callback = GetVM},
};
static JSVM\_CallbackStruct \*method = param;
// GetVM方法别名，供JS调用
static JSVM\_PropertyDescriptor descriptor\[\] = {
    {"getVM", nullptr, method++, nullptr, nullptr, nullptr, JSVM\_DEFAULT},
};

样例测试JS

const char \*srcCallNative = R"JS(getVM())JS";

预计的输出结果：

JSVM OH\_JSVM\_GetVM: success

#### \[h2\]OH\_JSVM\_GetHeapStatistics

返回一组虚拟机堆的统计数据。

cpp部分代码

// hello.cpp
#include "napi/native\_api.h"
#include "ark\_runtime/jsvm.h"
#include <hilog/log.h>

// OH\_JSVM\_GetHeapStatistics的样例方法
void PrintHeapStatistics(JSVM\_HeapStatistics result)
{
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap totalHeapSize: %{public}zu", result.totalHeapSize);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap totalHeapSizeExecutable: %{public}zu", result.totalHeapSizeExecutable);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap totalPhysicalSize: %{public}zu", result.totalPhysicalSize);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap totalAvailableSize: %{public}zu", result.totalAvailableSize);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap usedHeapSize: %{public}zu", result.usedHeapSize);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap heapSizeLimit: %{public}zu", result.heapSizeLimit);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap mallocedMemory: %{public}zu", result.mallocedMemory);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap externalMemory: %{public}zu", result.externalMemory);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap peakMallocedMemory: %{public}zu", result.peakMallocedMemory);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap numberOfNativeContexts: %{public}zu", result.numberOfNativeContexts);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap numberOfDetachedContexts: %{public}zu", result.numberOfDetachedContexts);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap totalGlobalHandlesSize: %{public}zu", result.totalGlobalHandlesSize);
    OH\_LOG\_INFO(LOG\_APP, "JSVM API heap usedGlobalHandlesSize: %{public}zu", result.usedGlobalHandlesSize);
}

static JSVM\_Value GetHeapStatistics(JSVM\_Env env, JSVM\_CallbackInfo info)
{
    // 获取当前虚拟机对象
    JSVM\_VM testVm;
    OH\_JSVM\_GetVM(env, &testVm);
    // 获取虚拟机的堆统计信息
    JSVM\_HeapStatistics result;
    OH\_JSVM\_GetHeapStatistics(testVm, &result);
    // 打印虚拟机堆统计信息
    PrintHeapStatistics(result);
    // 返回虚拟机堆统计信息中‘本机上下文数量’
    JSVM\_Value nativeContextsCnt = nullptr;
    OH\_JSVM\_CreateInt64(env, result.numberOfNativeContexts, &nativeContextsCnt);
    return nativeContextsCnt;
}
// GetHeapStatistics注册回调
static JSVM\_CallbackStruct param\[\] = {
    {.data = nullptr, .callback = GetHeapStatistics},
};
static JSVM\_CallbackStruct \*method = param;
// GetHeapStatistics方法别名，供JS调用
static JSVM\_PropertyDescriptor descriptor\[\] = {
    {"getHeapStatistics", nullptr, method++, nullptr, nullptr, nullptr, JSVM\_DEFAULT},
};

样例测试JS

const char \*srcCallNative = R"JS(getHeapStatistics())JS";

预计的输出结果（虚拟机堆的统计数据，会实时发生变化）：

JSVM API heap totalHeapSize: 1597440
JSVM API heap totalHeapSizeExecutable: 0
JSVM API heap totalPhysicalSize: 1323008
JSVM API heap totalAvailableSize: 1519203688
JSVM API heap usedHeapSize: 178256
JSVM API heap heapSizeLimit: 1518338048
JSVM API heap mallocedMemory: 32848
JSVM API heap externalMemory: 0
JSVM API heap peakMallocedMemory: 40960
JSVM API heap numberOfNativeContexts: 1
JSVM API heap numberOfDetachedContexts: 0
JSVM API heap totalGlobalHandlesSize: 8192
JSVM API heap usedGlobalHandlesSize: 32

以下接口的示例代码可以参考链接：

[JSVM-API调试&定位](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/jsvm-debugger-cpuprofiler-heapsnapshot)

#### \[h2\]OH\_JSVM\_StartCpuProfiler

创建并启动一个CPU profiler。

#### \[h2\]OH\_JSVM\_StopCpuProfiler

停止CPU profiler并将结果输出到流中。

#### \[h2\]OH\_JSVM\_TakeHeapSnapshot

获取当前堆快照并输出到流中。

#### \[h2\]OH\_JSVM\_OpenInspector

在指定的主机和端口上激活inspector，用于调试JS码。

#### \[h2\]OH\_JSVM\_CloseInspector

尝试关闭剩余的所有inspector连接。

#### \[h2\]OH\_JSVM\_WaitForDebugger

等待主机与inspector建立socket连接。连接建立后，程序将继续运行并发送Runtime.runIfWaitingForDebugger命令。