6

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();
}

初めて実行するgetMagicNumberと、正しく実行され、42が返されます。2回目に実行しようとすると、クラッシュします。

具体的には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;
}

これは、この問題によく似ています。これはv8::Locker、「分離株への排他的アクセス」を取得するために使用することを示唆しています。

Locker l;の上部にシンプルを追加することgetMagicNumberで、クラッシュが発生しなくなりました。私が注意を払っていないときに簡単に自分自身を壊す傾向がある自分自身を修正する問題。

これで問題が解決する理由については、ほとんど理解しv8::Lockerていません。また、非推奨の方法で使用しているコンパイラの警告が表示されます。推奨される方法は、のコンストラクターv8::Isolateへの引数としてを提供することv8::Lockerですが、分離を「取得」する方法がわかりません。

最終的に:v8の現在の状態に応じて、この問題を解決する適切な方法は何ですか。また、その理由は何ですか。

4

2 に答える 2

7

私が理解しているように、V8分離は、ヒープ、ガベージコレクター、および0個以上のV8コンテキストを備えたV8ランタイムのインスタンスです。分離株はスレッドセーフではないため、を介して保護する必要がありますv8::Locker

一般に、V8を使用するには、最初に分離を作成する必要があります。

v8::Isolate* isolate = v8::Isolate::New();

次に、任意のスレッドからの分離を使用するには:

v8::Locker locker(isolate);
v8::Isolate::Scope isolateScope(isolate);

この時点で、スレッドは分離を所有し、コンテキストの作成、スクリプトの実行などを自由に行うことができます。

現在、非常に単純なアプリケーションの利益のために、V8はデフォルトの分離を提供し、ロック要件を緩和しますが、常に同じスレッドからV8にアクセスする場合にのみ、これらの松葉杖を使用できます。2番目の呼び出しが別のスレッドから行われたため、アプリケーションが失敗したと思います。

于 2013-03-24T20:07:30.680 に答える
2

私は今V8を学んでいますが、あなたは電話する必要があると思います:

v8 :: Locker locker(isolate);

これにより、スタックに割り当てられたLockerオブジェクトが作成され、Isolateが別のスレッドで使用されるのをブロックします。現在の関数が戻ると、このスタックオブジェクトのデストラクタが自動的に呼び出され、Isolateのロックが解除されます。

電話する必要があります:

v8 :: Isolate :: ScopeisolateScope(isolate);

これにより、現在のスレッドがこの分離を実行するように設定されます。分離は1つのスレッドでのみ使用できます。Lockerはこれを強制しますが、Isolate自体を現在のスレッド用に構成する必要があります。これにより、現在のスレッドに関連付けられているIsolateを指定するスタック割り当てオブジェクトが作成されます。Lockerと同様に、この変数がスコープ外になると(現在の関数が戻るとき)、Scopeデストラクタが呼び出され、Isolateがデフォルトとして設定解除されます。V8 API呼び出しの多くは分離への参照を必要とするため、これが必要であると思いますが、パラメーターとして参照しないでください。したがって、直接アクセスできるものが必要です(おそらくスレッドごとの変数を介して)。

Isolate :: Scopeクラスが行うのは、コンストラクターでisolate :: Enter()を呼び出し、デストラクタでisolate :: Exit()を呼び出すことだけです。したがって、より詳細な制御が必要な場合は、Enter()/ Exit()を自分で呼び出すことができます。

于 2014-11-07T20:30:52.400 に答える