JSVM,既标准JS引擎,是严格遵守Ecmascript规范的JavaScript代码执行引擎。 详情参考: JSVM 。
基于JSVM的JS代码调试调优能力包括:Debugger、CPU Profiler、Heap Snapshot、Heap Statistics。涉及以下接口:
接口名 | 接口功能 |
---|---|
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_CloseInspector | 尝试关闭剩余的所有inspector连接。 |
OH_JSVM_WaitForDebugger | 等待主机与inspector建立socket连接,连接建立后程序将继续运行。发送Runtime.runIfWaitingForDebugger命令。 |
本文将介绍调试、CPU Profiler、Heap Snapshot的使用方法。
调试能力使用方法
调试步骤
- 在应用工程配置文件module.json中配置网络权限:
"requestPermissions": [{
"name": "ohos.permission.INTERNET",
"reason": "$string:app_name",
"usedScene": {
"abilities": [
"FromAbility"
],
"when": "inuse"
}
}]
- 为避免debugger过程中的暂停被误报为无响应异常,可以 开启DevEco Studio的Debug模式 (无需设置断点),或者可以在非主线程的其他线程中运行JSVM。
- 在执行JS代码之前,调用OH_JSVM_OpenInspector在指定的主机和端口上激活inspector,创建socket。例如OH_JSVM_OpenInspector(env, “localhost”, 9225),在端侧本机端口9225创建socket。
- 调用OH_JSVM_WaitForDebugger,等待建立socket连接。
- 检查端侧端口是否打开成功。hdc shell “netstat -anp | grep 9225”。结果为9225端口状态为“LISTEN"即可。
- 转发端口。hdc fport tcp:9229 tcp:9225。转发PC侧端口9229到端侧端口9225。结果为"Forwardport result:OK"即可。
- 在chrome浏览器地址栏输入"localhost:9229/json",回车。获取端口连接信息。拷贝"devtoolsFrontendUrl"字段url内容到地址栏,回车,进入DevTools源码页,将看到在应用中通过OH_JSVM_RunScript执行的JS源码,此时暂停在第一行JS源码处。
- 用户可在源码页打断点,通过按钮发出各种调试命令控制JS代码执行,并查看变量。
- 调用OH_JSVM_CloseInspector关闭inspector,结束socket连接。
示例代码
#include "ark_runtime/jsvm.h"
#include <string>
using namespace std;
// 待调试的JS源码
static string srcDebugger = R"JS(
const concat = (...args) => args.reduce((a, b) => a + b);
var dialogue = concat('"What ', 'is ', 'your ', 'name ', '?"');
dialogue = concat(dialogue, ' --', '"My ', 'name ', 'is ', 'Bob ', '."');
)JS";
// 开启debugger
static void EnableInspector(JSVM_Env env) {
// 在指定的主机和端口上激活inspector,创建socket。
OH_JSVM_OpenInspector(env, "localhost", 9225);
// 等待建立socket连接。
OH_JSVM_WaitForDebugger(env, true);
}
// 关闭debugger
static void CloseInspector(JSVM_Env env) {
// 关闭inspector,结束socket连接。
OH_JSVM_CloseInspector(env);
}
static void RunScript(JSVM_Env env) {
JSVM_HandleScope handleScope;
OH_JSVM_OpenHandleScope(env, &handleScope);
JSVM_Value jsSrc;
OH_JSVM_CreateStringUtf8(env, srcDebugger.c_str(), srcDebugger.size(), &jsSrc);
JSVM_Script script;
OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script);
JSVM_Value result;
OH_JSVM_RunScript(env, script, &result);
OH_JSVM_CloseHandleScope(env, handleScope);
}
void RunDemo() {
JSVM_InitOptions initOptions{};
OH_JSVM_Init(&initOptions);
JSVM_VM vm;
OH_JSVM_CreateVM(nullptr, &vm);
JSVM_VMScope vmScope;
OH_JSVM_OpenVMScope(vm, &vmScope);
JSVM_Env env;
OH_JSVM_CreateEnv(vm, 0, nullptr, &env);
// 执行JS代码之前打开debugger。
EnableInspector(env);
JSVM_EnvScope envScope;
OH_JSVM_OpenEnvScope(env, &envScope);
// 执行JS代码。
RunScript(env);
OH_JSVM_CloseEnvScope(env, envScope);
// 执行JS代码之后关闭debugger。
CloseInspector(env);
OH_JSVM_DestroyEnv(env);
OH_JSVM_CloseVMScope(vm, vmScope);
OH_JSVM_DestroyVM(vm);
}
CPU Profiler及Heap Snapshot使用方法
CPU Profiler接口使用方法
- 在执行JS代码之前,调用OH_JSVM_StartCpuProfiler开始采样并返回JSVM_CpuProfiler。
- 在执行JS代码后,调用OH_JSVM_StopCpuProfiler,传入1中返回的JSVM_CpuProfiler,传入输出流回调及输出流指针。数据将会写入指定的输出流中。
- 输出数据为JSON字符串。可存入.cpuprofile文件中。该文件类型可导入Chrome浏览器-DevTools-JavaScript Profiler工具中解析成性能分析视图。
Heap Snapshot接口使用方法
1.为分析某段JS代码的堆对象创建情况。可在执行JS代码前后,分别调用一次OH_JSVM_TakeHeapSnapshot。传入输出流回调及输出流指针。数据将会写入指定的输出流中。
2.输出数据可存入.heapsnapshot文件中。该文件类型可导入Chrome浏览器-DevTools-Memory工具中解析成内存分析视图。
示例代码
#include "ark_runtime/jsvm.h"
#include <fstream>
#include <iostream>
using namespace std;
// 待调优的JS代码。
static string srcProf = R"JS(
function sleep(delay) {
var start = (new Date()).getTime();
while ((new Date()).getTime() - start < delay) {
continue;
}
}
function work3() {
sleep(300);
}
function work2() {
work3();
sleep(200);
}
function work1() {
work2();
sleep(100);
}
work1();
)JS";
// 数据输出流回调,用户自定义,处理返回的调优数据,此处以写入文件为例。
static bool OutputStream(const char *data, int size, void *streamData) {
auto &os = *reinterpret_cast<ofstream *>(streamData);
if (data) {
os.write(data, size);
} else {
os.close();
}
return true;
}
static JSVM_CpuProfiler ProfilingBegin(JSVM_VM vm) {
// 文件输出流,保存调优数据,/data/storage/el2/base/files为沙箱路径。以包名为com.example.helloworld为例。
// 实际文件会保存到/data/app/el2/100/base/com.example.helloworld/files/heap-snapshot-begin.heapsnapshot。
ofstream heapSnapshot("/data/storage/el2/base/files/heap-snapshot-begin.heapsnapshot",
ios::out | ios:: binary | ios::trunc);
// 执行JS前获取一次Heap Snapshot数据。
OH_JSVM_TakeHeapSnapshot(vm, OutputStream, &heapSnapshot);
JSVM_CpuProfiler cpuProfiler;
// 开启CPU Profiler。
OH_JSVM_StartCpuProfiler(vm, &cpuProfiler);
return cpuProfiler;
}
// 关闭调优数据采集工具
static void ProfilingEnd(JSVM_VM vm, JSVM_CpuProfiler cpuProfiler) {
// 文件输出流,保存调优数据,/data/storage/el2/base/files为沙箱路径。以包名为com.example.helloworld为例。
// 实际文件会保存到/data/app/el2/100/base/com.example.helloworld/files/cpu-profile.cpuprofile。
ofstream cpuProfile("/data/storage/el2/base/files/cpu-profile.cpuprofile",
ios::out | ios:: binary | ios::trunc);
// 关闭CPU Profiler,获取数据。
OH_JSVM_StopCpuProfiler(vm, cpuProfiler, OutputStream, &cpuProfile);
ofstream heapSnapshot("/data/storage/el2/base/files/heap-snapshot-end.heapsnapshot",
ios::out | ios:: binary | ios::trunc);
// 执行JS后再获取一次Heap Snapshot数据,与执行前数据作对比,以分析内存问题或者进行内存调优。
OH_JSVM_TakeHeapSnapshot(vm, OutputStream, &heapSnapshot);
}
static void RunScriptWithStatistics(JSVM_Env env) {
JSVM_VM vm;
OH_JSVM_GetVM(env, &vm);
// 开始调优。
auto cpuProfiler = ProfilingBegin(vm);
JSVM_HandleScope handleScope;
OH_JSVM_OpenHandleScope(env, &handleScope);
JSVM_Value jsSrc;
OH_JSVM_CreateStringUtf8(env, srcProf.c_str(), srcProf.size(), &jsSrc);
JSVM_Script script;
OH_JSVM_CompileScript(env, jsSrc, nullptr, 0, true, nullptr, &script);
JSVM_Value result;
// 执行JS代码。
OH_JSVM_RunScript(env, script, &result);
OH_JSVM_CloseHandleScope(env, handleScope);
// 结束调优。
ProfilingEnd(vm, cpuProfiler);
}
void RunDemo() {
JSVM_InitOptions initOptions{};
OH_JSVM_Init(&initOptions);
JSVM_VM vm;
OH_JSVM_CreateVM(nullptr, &vm);
JSVM_VMScope vmScope;
OH_JSVM_OpenVMScope(vm, &vmScope);
JSVM_Env env;
OH_JSVM_CreateEnv(vm, 0, nullptr, &env);
JSVM_EnvScope envScope;
OH_JSVM_OpenEnvScope(env, &envScope);
RunScriptWithStatistics(env);
OH_JSVM_CloseEnvScope(env, envScope);
OH_JSVM_DestroyEnv(env);
OH_JSVM_CloseVMScope(vm, vmScope);
OH_JSVM_DestroyVM(vm);
}
鸿蒙全栈开发全新学习指南
之前总有很多小伙伴向我反馈说,不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以这里为大家准备了一份实用的鸿蒙(HarmonyOS NEXT)学习路线与学习文档用来跟着学习是非常有必要的。
针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。
本路线共分为四个阶段:
第一阶段:鸿蒙初中级开发必备技能
第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH
第三阶段:应用开发中高级就业技术
第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH
《鸿蒙 (Harmony OS)开发学习手册》(共计892页)
如何快速入门?
1.基本概念
2.构建第一个ArkTS应用
3.……
开发基础知识:gitee.com/MNxiaona/733GH
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……
基于ArkTS 开发
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……
鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH
鸿蒙入门教学视频:
美团APP实战开发教学:gitee.com/MNxiaona/733GH
写在最后
- 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:
gitee.com/MNxiaona/733GH