# Debugging and Profiling JS Code Using JSVM-API ## Introduction JSVM-API provide APIs for retrieving JavaScript virtual machine (JSVM) instances and performing memory analysis, profiling, and debugging, which facilitates code optimization and improves development efficiency. ## Basic Concepts - JSVM: A JSVM is an environment for executing JavaScript (JS) code. It parses and executes JS code, manages memory, and provides interaction with other system resources. For example, you can use **OH_JSVM_GetVM** to retrieve JSVM instances in a specific environment. This is one of the basic JSVM management operations. - Debug: As an important activity in program development, debugging involves locating, analyzing, and rectifying code errors. For example, you can use **OH_JSVM_OpenInspector** to open inspector, a tool used to debug JS code, on a host and port and view the running status of an application on a real-time basis. You can use **OH_JSVM_CloseInspector** to close inspector. ## Available APIs | API | Description | |----------------------------|--------------------------------| | OH_JSVM_GetVM | Obtains a VM instance.| | OH_JSVM_GetHeapStatistics | Obtains heap statistics of a VM.| | OH_JSVM_StartCpuProfiler | Creates and starts a CPU profiler instance.| | OH_JSVM_StopCpuProfiler | Stops the CPU profiler and outputs the result to a stream.| | OH_JSVM_TakeHeapSnapshot | Obtains a snapshot of the current heap and outputs it to a stream.| | OH_JSVM_OpenInspector | Opens an inspector instance on the specified host and port for debugging JS code.| | OH_JSVM_CloseInspector | Closes all remaining inspector connections.| | OH_JSVM_WaitForDebugger | Waits for the host to set up a socket connection with an inspector. After the connection is set up, the application continues to run. You can use **Runtime.runIfWaitingForDebugger** to run paused targets.| ## Example If you are just starting out with JSVM-API, see [JSVM-API Development Process](use-jsvm-process.md). The following demonstrates only the C++ code involved in debugging and profiling JS code. ### OH_JSVM_GetVM Use **OH_JSVM_GetVM** to obtain a VM instance. CPP code: ```cpp // hello.cpp #include "napi/native_api.h" #include "ark_runtime/jsvm.h" #include <hilog/log.h> // Define OH_JSVM_GetVM. static JSVM_Value GetVM(JSVM_Env env, JSVM_CallbackInfo info) { // Obtain a VM instance for subsequent VM-related operations or analysis. 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; } // Register the GetVM callback. static JSVM_CallbackStruct param[] = { {.data = nullptr, .callback = GetVM}, }; static JSVM_CallbackStruct *method = param; // Set a property descriptor named getVM and associate it with a callback. This allows the GetVM callback to be called from JS. static JSVM_PropertyDescriptor descriptor[] = { {"getVM", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, }; ``` // Call C++ code from JS. ```c++ const char *srcCallNative = R"JS(getVM())JS"; ``` ### OH_JSVM_GetHeapStatistics Use **OH_JSVM_GetHeapStatistics** to obtain heap statistics of a VM. CPP code: ```cpp // hello.cpp #include "napi/native_api.h" #include "ark_runtime/jsvm.h" #include <hilog/log.h> // Define 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) { // Obtain the VM instance. JSVM_VM testVm; OH_JSVM_GetVM(env, &testVm); // Obtain the heap statistics of the VM. JSVM_HeapStatistics result; OH_JSVM_GetHeapStatistics(testVm, &result); // Print VM heap statistics. PrintHeapStatistics(result); // Return the number of local contexts in the VM heap statistics. JSVM_Value nativeContextsCnt = nullptr; OH_JSVM_CreateInt64(env, result.numberOfNativeContexts, &nativeContextsCnt); return nativeContextsCnt; } // Register the GetHeapStatistics callback. static JSVM_CallbackStruct param[] = { {.data = nullptr, .callback = GetHeapStatistics}, }; static JSVM_CallbackStruct *method = param; // Set a property descriptor named getHeapStatistics and associate it with a callback. This allows the GetHeapStatistics callback to be called from JS. static JSVM_PropertyDescriptor descriptor[] = { {"getHeapStatistics", nullptr, method++, nullptr, nullptr, nullptr, JSVM_DEFAULT}, }; ``` // Call C++ code from JS. ```c++ const char *srcCallNative = R"JS(getHeapStatistics())JS"; ``` For details about the sample code of the previous APIs, see: [JSVM Debugging and Profiling](jsvm-debugger-cpuprofiler-heapsnapshot.md) ### OH_JSVM_StartCpuProfiler Use **OH_JSVM_StartCpuProfiler** to create and start a CPU profiler instance. ### OH_JSVM_StopCpuProfiler Use **OH_JSVM_StopCpuProfiler** to stop the CPU profiler and output the result to a stream. ### OH_JSVM_TakeHeapSnapshot Use **OH_JSVM_TakeHeapSnapshot** to obtain a snapshot of the current heap and output it to a stream. ### OH_JSVM_OpenInspector Use **OH_JSVM_OpenInspector** to open an inspector instance on the specified host and port for debugging JS code. ### OH_JSVM_CloseInspector Use **OH_JSVM_CloseInspector** to close all remaining inspector connections. ### OH_JSVM_WaitForDebugger Use **OH_JSVM_WaitForDebugger** to wait for the host to set up a socket connection with an inspector. After the connection is set up, the application continues to run. You can use **Runtime.runIfWaitingForDebugger** to run paused targets.