异步调用如何获取JNI接口指针(JNIEnv *) [英] How to obtain JNI interface pointer (JNIEnv *) for asynchronous calls
问题描述
我了解到 JNI 接口指针 (JNIEnv *) 仅在当前线程中有效.假设我在本地方法中启动了一个新线程;它如何将事件异步发送到 Java 方法?因为这个新线程不能有 (JNIEnv *) 的引用.为 (JNIEnv *) 存储全局变量显然不起作用?
I have learned that the JNI interface pointer (JNIEnv *) is only valid in the current thread. Suppose I started a new thread inside a native method; how it can asynchronously send events to a Java method? As this new thread can't have a reference of (JNIEnv *). Storing a global variable for (JNIEnv *) apparently will not work?
推荐答案
在使用 JNI 从 Java 到 C++ 的环境"同步调用中已经由 JVM 设置,但是从任意 C++ 线程转向另一个方向,它可能没有
Within synchronous calls using JNI from Java to C++ the "environment" has already been setup by the JVM, however going in the other direction from an arbitrary C++ thread it may not have been
因此您需要按照以下步骤操作
Therefore you need to follow these steps
- 使用
GetEnv
获取 JVM 环境上下文 - 如有必要,使用
AttachCurrentThread
附加上下文 - 使用
CallVoidMethod
正常调用方法 - 使用
DetachCurrentThread
分离
完整示例.请注意,我过去曾在我的 博客
Full example. Note I have written about this in the past in more detail on my blog
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();
}
这篇关于异步调用如何获取JNI接口指针(JNIEnv *)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!