一、前言
在JNI开发时,最重要的就是JNIEnv *env这个参数,它代表着Java本地接口环境(Java Native Interface Environment),通过它可以在native层中与java层进行交互。因此在每个定义的native方法中都有这个参数。
二、问题描述
在项目中遇到的一个问题就是在native层中的回调函数里调用java层的方法,实时向java层传输算法结果,这里就需要在回调函数中定义JNIEnv *env这个参数。我当时认为只要定义一个全局变量env,在其他方法中进行赋值,然后就能在回调函数中使用了,其实是错的!当然我也这么试了,最终结果是程序直接挂掉!
事实上,JNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立。JavaVM是虚拟机在JNI层的代表,在一个虚拟机进程中只有一个JavaVM,因此该进程的所有线程都可以使用这个JavaVM。当后台线程需要调用JNIEnv时,在native层中使用全局变量保存JavaVM尤为重要,这样使得后台线程能通过JavaVM获得JNIEnv。
三、问题解决
1、定义一个全局变量JavaVM:
JavaVM* g_jvm = NULL;
//在某个含有env环境的方法中获取JavaVM
env->GetJavaVM(&_jvm);
或者可以在JNI_OnLoad中进行赋值,因为它是最开始执行的函数
jint