39

グローバルに保存しJNIEnvているので、後で静的 Java メソッドを呼び出すことができます。しかし、へのグローバル ポインタを格納するJNIEnv必要があるか、他の Java オブジェクトと同じように格納する必要があるか、それともこれを必要としない特殊なケースか。

JNIEnv* globalEnvPointer;

[JNICALL etc] void init(JNIENv* env, [etc])
{
   //required?
   globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env);
   //or is this OK?
   globalEnvPointer = env;
}

編集

私はここで少しばかげています. を使用するすべてのメソッドはglobalEnvPointerinit 内で呼び出されます. myinitは実際には私のcプログラムのmainメソッドであり、プログラムの最後まで戻りません. また、c プログラムで他のスレッドを使用していません。これにより、答えが簡単になると思います。

JNIEnv* globalEnvPointer;

[JNICALL etc] void main(JNIENv* env, [etc])
{
   //required?
   globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env);
   //or is this OK?
   globalEnvPointer = env;
   someMethod();
}

void someMethod()
{
   //use globalEnvPointer here
}
4

1 に答える 1

54

JNIEnvポインターをキャッシュすることはできません。ここでそれについて読んでください

JNI インターフェース ポインター (JNIEnv) は、現在のスレッドでのみ有効です。別のスレッドが Java VM にアクセスする必要がある場合、最初に AttachCurrentThread() を呼び出して自分自身を VM にアタッチし、JNI インターフェース ポインターを取得する必要があります。VM にアタッチされると、ネイティブ スレッドは、ネイティブ メソッド内で実行される通常の Java スレッドと同じように機能します。ネイティブ スレッドは、DetachCurrentThread() を呼び出して自分自身を切り離すまで、VM に接続されたままになります。

できることは、JavaVM代わりにポインターをキャッシュすることです。

static JavaVM *jvm;

[JNICALL etc] void init(JNIENv* env, [etc])
{
   jint rs = (*env)->GetJavaVM(env, &jvm);
   assert (rs == JNI_OK);
}

そして、必要なときはいつでもJNIEnv、それが与えられていないコンテキストからのポインターがこれを行います:

void someCallback() {
    JNIEnv *env;
    jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
    assert (rs == JNI_OK);
    // Use the env pointer...
}

ただし、Java からネイティブ メソッドを呼び出すときは常に、使用する env ポインターが与えられます。

JNIEXPORT jint JNICALL Java_package_Class_method(JNIEnv *env, jobject obj) {
    // just use the env pointer as is.
}
于 2012-09-14T09:09:29.107 に答える