我将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
}
答案 0 :(得分:49)
您无法缓存JNIEnv
指针。阅读here:
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.
}