OpenHarmony ArkUI - ets_runtime启动流程源码解读 原创 精华
作者:张志成
前言
本文基于OpenHarmony源码梳理应用的启动过程,介绍appspawn/ability_runtime/ace_engine/ets_runtime等重要模块的初始化流程,以及它们之间的相互关系。
不同形态的hap应用在具体细节上会有一些差异,但整体的流程上是一致的。本文基于OpenHarmoney 3.2标准系统 FA模式的ets应用进行阐述。
1. 应用启动整体流程
查看各个进程的父子关系可知,OpenHarmony的系统应用和用户应用进程,都是由应用孵化器(appspawn)拉起的。
应用启动的整理流程如下图所示:
说明: 应用启动时,appspawn进程会fork出一个应用子进程,创建AceAbility实现类和AceContainer。AceContainer初始化过程中会在JS线程中创建JS运行环境,包括JsEngine、NativeEngin、ArkJSRuntime、JSThread、EcmaVM等重要组件。
2. 启动流程详解
2.1 appspawn 创建应用进程
应用日志:
关键代码流程:
2.2 应用主线程初始化Ability
应用的整体状态流转是由Ability实例对象来控制完成的。因此应用进程拉起时,会先创建出Ability。不同的应用模型在这里会创建不同的实例类型:
AbilityImpl实例创建后,应用开始进入Start状态,触发AceAbility::OnStart()回调。在该回调中,会创建JS运行环境。
2.3 AceContainer初始化
AceContainer初始化可分为两个阶段:
第一个阶段创建JS运行时环境(js_engine, native_engine, ets_runtime);
第二个阶段调度js_engine开始读取js字节码文件(xxx.abc)
2.3.1 阶段一:创建JS运行时环境
这里的代码流程比较长… 具体调用过程见上图说明。讲几个主要的点:
-
AceContianer初始化时会创建一个任务执行线程 FlutterTaskExecutor,这就是后续js代码的执行线程。 应用主线程把需要在js线程中执行的代码包装成task,放到FlutterTaskExecutor中去执行。
-
创建Js引擎时可以选择不同的引擎类型,这是在源码编译阶段由宏开关控制的。
\foundation\arkui\ace_engine\frameworks\bridge\declarative_frontend\engine\declarative_engine_loader.cpp
宏开关在如下配置文件中定义:
foundation/arkui/ace_engine/adapter/ohos/build/config.gni
-
ArkNativeEngine初始化时创建了NAPI层的各个重要组件(moduleManager, scopeManager, referenceManager, loop…)
-
ArkNativeEngine向js运行环境中注册了一个"requireNapi()"方法,该方法是js应用import各种NAPI库的入口。
js代码中的"import xxxx"在hap包编译阶段会改写为“requireNapi(xxx)”,当这行代码被js引擎解释执行时,即会调用到 ArkNativeEngine 中注册的requireNapi c++实现代码,通过NAPI的ModuleManager 模块完成 xxxNAPI模块lib库的加载。
2.3.2 阶段二:读取并执行js字节码文件
在 AceContainer::RunPage() 流程中,会依次创建两个js线程的task, 分别读取 app.abc和index.abc文件。
细节1: JsiDeclarativeEngine::LoadJs()方法中是根据传入的*.js文件名去读取对应的*.abc
细节2:EcmaVM::InvokeEcmaEntrypoint() 方法中会执行index.abc中的入口函数func_main_0, 该函数在原始的index.js文件中并没有,是hap包编译后生成在index.abc文件中的。
更多原创内容请关注:深开鸿技术团队
入门到精通、技巧到案例,系统化分享OpenHarmony开发技术,欢迎投稿和订阅,让我们一起携手前行共建生态。
这个流程图太详细了,必须佩服
点赞,很详细的讲解
很明了的流程总结
请问下,查看进程信息,以及线程信息的命令是什么?