2.4.3 JNIEnv介绍
最后更新于:2022-04-02 05:48:18
NIEnv是一个和线程相关的,代表JNI环境的结构体,图2-3展示了JNIEnv的内部结构:
:-: ![](http://img.blog.csdn.net/20150802093747105?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图2-3 JNIEnv内部结构简图
从上图可知,JNIEnv实际上就是提供了一些JNI系统函数。通过这些函数可以做到:
- 调用Java的函数。
- 操作jobject对象等很多事情。
后面小节中将具体介绍怎么使用JNIEnv中的函数。这里,先介绍一个关于JNIEnv的重要知识点。
上面提到说JNIEnv,是一个和线程有关的变量。也就是说,线程A有一个JNIEnv,线程B有一个JNIEnv。由于线程相关,所以不能在线程B中使用线程A的JNIEnv结构体。读者可能会问,JNIEnv不都是native函数转换成JNI层函数后由虚拟机传进来的吗?使用传进来的这个JNIEnv总不会错吧?是的,在这种情况下使用当然不会出错。不过当后台线程收到一个网络消息,而又需要由Native层函数主动回调Java层函数时,JNIEnv是从何而来呢?根据前面的介绍可知,我们不能保存另外一个线程的JNIEnv结构体,然后把它放到后台线程中来用。这该如何是好?
还记得前面介绍的那个JNI_OnLoad函数吗?它的第一个参数是JavaVM,它是虚拟机在JNI层的代表,代码如下所示:
~~~
//全进程只有一个JavaVM对象,所以可以保存,任何地方使用都没有问题。
jint JNI_OnLoad(JavaVM* vm, void* reserved)
~~~
正如上面代码所说,不论进程中有多少个线程,JavaVM却是独此一份,所以在任何地方都可以使用它。那么,JavaVM和JNIEnv又有什么关系呢?答案如下:
- 调用JavaVM的AttachCurrentThread函数,就可得到这个线程的JNIEnv结构体。这样就可以在后台线程中回调Java函数了。
- 另外,后台线程退出前,需要调用JavaVM的DetachCurrentThread函数来释放对应的资源。
再来看JNIEnv的作用。
';