如何获取用于异步调用的 JNI 接口指针 (JNIEnv *)
2022-08-31 12:13:25
我了解到JNI接口指针(JNIEnv *)仅在当前线程中有效。假设我在本机方法中启动了一个新线程;它如何将事件异步发送到Java方法?由于此新线程不能具有 (JNIEnv * ) 的引用。存储 (JNIEnv *) 的全局变量显然不起作用?
我了解到JNI接口指针(JNIEnv *)仅在当前线程中有效。假设我在本机方法中启动了一个新线程;它如何将事件异步发送到Java方法?由于此新线程不能具有 (JNIEnv * ) 的引用。存储 (JNIEnv *) 的全局变量显然不起作用?
您可以使用 JNIEnv->GetJavaVM 获取指向 JVM
() 的指针。您可以安全地将该指针存储为全局变量。稍后,在新线程中,如果您使用C / C++创建了新线程,则可以使用AttetchCurrentThread
将新线程附加到JVM,或者如果您使用java代码创建了线程,则只需GetEnv
,我不认为,因为JNI会给您传递一个然后,并且您不会遇到此问题。JavaVM*
JNIEnv*
// JNIEnv* env; (initialized somewhere else)
JavaVM* jvm;
env->GetJavaVM(&jvm);
// now you can store jvm somewhere
// in the new thread:
JNIEnv* myNewEnv;
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6; // choose your JNI version
args.name = NULL; // you might want to give the java thread a name
args.group = NULL; // you might want to assign the java thread to a ThreadGroup
jvm->AttachCurrentThread((void**)&myNewEnv, &args);
// And now you can use myNewEnv
在使用JNI从Java到C++同步调用中,“环境”已经由JVM设置,但是从任意C++线程向另一个方向移动,它可能不是
因此,您需要按照以下步骤操作
GetEnv
AttachCurrentThread
CallVoidMethod
DetachCurrentThread
完整示例。注意 我过去在我的博客上写过更详细的文章
JavaVM* g_vm;
env->GetJavaVM(&g_vm);
void callback(int val) {
JNIEnv * g_env;
// double check it's all ok
int getEnvStat = g_vm->GetEnv((void **)&g_env, JNI_VERSION_1_6);
if (getEnvStat == JNI_EDETACHED) {
std::cout << "GetEnv: not attached" << std::endl;
if (g_vm->AttachCurrentThread((void **) &g_env, NULL) != 0) {
std::cout << "Failed to attach" << std::endl;
}
} else if (getEnvStat == JNI_OK) {
//
} else if (getEnvStat == JNI_EVERSION) {
std::cout << "GetEnv: version not supported" << std::endl;
}
g_env->CallVoidMethod(g_obj, g_mid, val);
if (g_env->ExceptionCheck()) {
g_env->ExceptionDescribe();
}
g_vm->DetachCurrentThread();
}