如何获取异步调用的JNI接口指针(JNIEnv *)


75

我了解到JNI接口指针(JNIEnv *)仅在当前线程中有效。假设我在本机方法中启动了一个新线程;如何将事件异步发送到Java方法?由于此新线程不能具有(JNIEnv *)的引用。为(JNIEnv *)存储全局变量显然无法正常工作吗?

Answers:


78

在使用从Java到C ++的JNI进行的同步调用中,JVM已设置了“环境”,但是从任意C ++线程的另一个方向来看,可能没有

因此,您需要按照以下步骤

  • 使用以下内容掌握JVM环境上下文 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();
}

13
与该问题相关的答案只有GetEnvAttachCurrentThread并且DetachCurrentThread甚至没有解释。

1
那完全解决了我的问题,但是上面的主要解释很美
Akhilesh

g_obj = env-> NewGlobalRef(obj); ------->抛出错误:请求成员“ NewGlobalRef”使用非结构体或联合体
Maical

我自己解决了上述错误。我将文件另存为.c,但使用的是c ++语法。
Maical 2015年

谢谢!这似乎已经解决了我应用程序中一个非常顽固但间歇性的问题。
艾伦·金纳曼

89

您可以使用来获得指向JVM(JavaVM*)的指针JNIEnv->GetJavaVM。您可以安全地将该指针存储为全局变量。以后,在新线程中,AttachCurrentThread如果您是用C / C ++创建的,则可以用来将新线程附加到JVM,或者只是GetEnv用Java代码创建的线程(我不认为这是因为JNI会给您传递JNIEnv*then和你不会有这个问题。


16
请注意,AttachCurrentThread如果您不需要任何特殊设置,则to的第二个参数可以为NULL,并且DetachCurrentThread如果不附加开头,则应确保在完成时调用(否则,您将积累无用的Thread对象,这些对象可以(永远不会被GC))。
技术

在NDK r9中,AttachCurrentThread函数的定义发生了变化。这是文档链接。docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/…–
Zephyr

不应该JNIEnv->GetJavaVM接受env作为第一个参数吗?
Denis Kniazhev 2014年

@DenisKniazhevenv基本上第一个参数,因为它GetJavaVM是在env指针上调用的。

2
@DenisKniazhev正确。C没有类,因此您不能在指针上调用方法。在C ++中,JNI提供了自动传递env指针的包装器类,但是在C中,您必须手动传递它。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.