首页 > 解决方案 > 为什么 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 设计为只初始化一次。如果我需要再次处理和初始化,我该怎么办?谢谢

标签: androidv8embedded-v8

解决方案


V8 使用“隔离”的概念,它们是它的独立实例。尝试根据需要创建和销毁它们,而不是尝试处理和重新初始化整个引擎。这应该可以为您节省几乎所有的内存,同时避免以非设计方式使用 V8 所产生的任何问题。


推荐阅读