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

编辑

我在这里有点笨,所有将使用的方法globalEnvPointer,都在我的 init 中调用,因为 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 线程一样工作。本机线程一直连接到 VM,直到它调用 DetachCurrentThread() 来分离自己。

您可以做的是缓存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 回答