使用v8 :: Locker的正确方法是什么,为什么我必须使用它?

nam*_*uol 6 java java-native-interface android v8

我正在尝试使用NDK在一个Android应用程序中嵌入v8.

我有一个看起来像这样的JNI模块(JNI映射代码未显示):

#include <jni.h>
#include <android/log.h>

#include <v8.h>
using namespace v8;

static jlong getMagicNumber() {
  HandleScope handle_scope;
  Persistent<Context> context = Context::New();
  Context::Scope context_scope(context);

  Handle<String> source = String::New("40 + 2");

  Handle<Script> script = Script::Compile(source);
  Handle<Value> result = script->Run();

  context.Dispose();

  return result->NumberValue();
}
Run Code Online (Sandbox Code Playgroud)

我第一次运行getMagicNumber,它正确运行并返回42.第二次我尝试运行它,它崩溃了.

具体来说,这ASSERT在v8中看到的isolate.h失败了:

// Returns the isolate inside which the current thread is running.
INLINE(static Isolate* Current()) {
  Isolate* isolate = reinterpret_cast<Isolate*>(
      Thread::GetExistingThreadLocal(isolate_key_));
  ASSERT(isolate != NULL);
  return isolate;
}
Run Code Online (Sandbox Code Playgroud)

这听起来很像这个问题,建议使用v8::Locker"独立访问隔离".

通过添加一个简单Locker l;的顶部getMagicNumber,崩溃不再发生.当我没有注意时,自我修复的问题很容易打破.

我只是最简单地理解为什么这可以解决我的问题,而且我正在收到编译器警告,我正在v8::Locker以不赞成使用的方式使用它.推荐的方法是为它提供一个v8::Isolate作为v8::Locker构造函数的参数,但我不知道我应该如何"获得"一个隔离.

最终:根据v8的当前状态解决这个问题的正确方法是什么?为什么

Bit*_*tex 7

据我了解,V8隔离是V8运行时的一个实例,包括堆,垃圾收集器和零个或多个V8上下文.隔离区不是线程安全的,必须通过保护v8::Locker.

通常,要使用V8,您必须首先创建隔离:

v8::Isolate* isolate = v8::Isolate::New();
Run Code Online (Sandbox Code Playgroud)

然后,使用任何线程的隔离:

v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);
Run Code Online (Sandbox Code Playgroud)

此时线程拥有隔离,可以自由创建上下文,执行脚本等.

现在,为了非常简单的应用程序的优势,V8提供了一个默认隔离并放宽了锁定要求,但如果您始终从同一个线程访问V8,则只能使用这些拐杖.我的猜测是你的应用程序失败了,因为第二次调用来自另一个线程.