android - 为什么 JavaScript v8 引擎设计为每个进程只能初始化一次?
问题描述
我的 Android 项目使用 JavaScript v8 引擎。我们只在几个页面中使用 v8 引擎,而不是在应用程序的整个生命周期中使用。我们发现 JavaScript v8 引擎占用了大量内存(超过 100M),并创建了一些工作线程。因为我们只在几个页面中使用 v8,所以当关闭这些页面时,我们尝试像下面这样处理 v8:
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
那么当再次进入 v8 页面时,我们需要再次初始化 v8,如下所示:
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
但是在初始化 v8 之后,代码会在下面崩溃:
art_sigsegv_fault 0x0000007c07a7c2e8
art::FaultManager::HandleFault(int, siginfo*, void*) 0x0000007c07a7c7fc
art::SignalChain::Handler(int, siginfo*, void*) 0x0000005619525e54
<unknown> 0x0000007e9e6668b0
v8::internal::wasm::WasmEngine::AddIsolate(v8::internal::Isolate*) 0x0000007b97ddc608
v8::internal::wasm::WasmEngine::AddIsolate(v8::internal::Isolate*) 0x0000007b97ddc608
v8::internal::Isolate::Init(v8::internal::ReadOnlyDeserializer*, v8::internal::StartupDeserializer*) 0x0000007b97b25b80
v8::internal::Isolate::InitWithSnapshot(v8::internal::ReadOnlyDeserializer*, v8::internal::StartupDeserializer*) 0x0000007b97b260b0
v8::internal::Snapshot::Initialize(v8::internal::Isolate*) 0x0000007b97dc07b4
v8::Isolate::Initialize(v8::Isolate*, v8::Isolate::CreateParams const&) 0x0000007b97aa1270
v8::Isolate::New(v8::Isolate::CreateParams const&) 0x0000007b97aa1370
se::ScriptEngine::init() ScriptEngine.cpp:412
se::ScriptEngine::start() ScriptEngine.cpp:588
Game::init() Game.cpp:59
(anonymous namespace)::createGame(ANativeWindow*) JniCocosActivity.cpp:57
(anonymous namespace)::preExecCmd(signed char) JniCocosActivity.cpp:87
(anonymous namespace)::glThreadEntry() JniCocosActivity.cpp:134
decltype(std::__ndk1::forward<void (*)()>(fp)()) std::__ndk1::__invoke<void (*)()>(void (*&&)()) type_traits:4353
void std::__ndk1::__thread_execute<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct> >, void (*)()>(std::__ndk1::tuple<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct> >, void (*)()>&, std::__ndk1::__tuple_indices<>) thread:342
void* std::__ndk1::__thread_proxy<std::__ndk1::tuple<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct> >, void (*)()> >(void*) thread:352
__pthread_start(void*) 0x0000007e997b4d50
__start_thread 0x0000007e9975528c
挖掘 v8 代码后,我发现 v8 似乎只允许每个进程初始化一次。因为有如下代码:
bool V8::Initialize() {
InitializeOncePerProcess();
return true;
}
及以下:
Isolate::InitializeOncePerProcess();
#if defined(USE_SIMULATOR)
Simulator::InitializeOncePerProcess();
#endif
CpuFeatures::Probe(false);
ElementsAccessor::InitializeOncePerProcess();
Bootstrapper::InitializeOncePerProcess();
CallDescriptors::InitializeOncePerProcess();
wasm::WasmEngine::InitializeOncePerProcess();
所以我的问题是:为什么 v8 设计为只初始化一次。如果我需要再次处理和初始化,我该怎么办?谢谢
解决方案
V8 使用“隔离”的概念,它们是它的独立实例。尝试根据需要创建和销毁它们,而不是尝试处理和重新初始化整个引擎。这应该可以为您节省几乎所有的内存,同时避免以非设计方式使用 V8 所产生的任何问题。
推荐阅读
- javascript - Javascript正则表达式在字符串中选择不同的内容
- java - 从树中返回一个字符串值
- c++ - 在 Visual Studio 2017 中将“头文件”(文件夹名称)从中文更改为英文
- java - 将 Map 值转换为字符串
- javascript - 无法读取未定义问题的属性
- google-calendar-api - 如何在 ruby 中使用谷歌日历 API 获取工作时间?
- botframework - 如何在我的网站上嵌入 Microsoft Bot Emulator
- vue.js - 鼠标按住时的 Vue 事件监听器
- windows-10 - 怎么解决这个问题,这个microsoft office的副本没有激活?
- python - 如何使用 GPflow 从多个链中采样?