保持对JNIEnv环境的全局引用

我将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中调用,因为我的init实际上是我的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 } 

您无法缓存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. }