JNIEnv是什么?
在《深入理解Android:卷1》- JNI层(一)中,在JNI函数的注册方法中,不管是静态方法还是动态方法,其函数参数中第一个参数是一个接口指针,类型为JNIEnv。
JNIEnv类型实际上代表了Java在本线程的运行环境,通过这个JNIEnv* 指针,就可以对Java端的代码进行操作。JNIEnv的指针会被JNI传入到本地方法的实现函数中来对Java端的代码进行操作。
JNIEnv内部结构和作用
JNIEnv是一个指向指针的指针,这个指针指向一个指针数组,指针数组中的每个指针指向接口函数。
Description of Figure Interface Pointer.png这些接口函数的作用有两个:
- 调用Java的函数(JNIEnv 代表 Java 运行环境,可以使用 JNIEnv 调用 Java 中的代码)
- 操作jobject对象(Java层的对象到JNI层就是jobject对象,需要用JNIEnv来操作这个对象)
一个Java对象包括:
- 成员变量
- 成员函数
操作Java对象的本质就是操作这些对象的成员变量和成员函数,Java对象除了少数几个外,在JNI层都会用object来表示对象的数据类型。
在JNI规则中,用 jfieldID和jmethodID来表示Java类的成员变量和成员函数:
- jfieldID表示Java类的成员变量
- jmethodID表示Java类的成员函数
jfieldID和jmethodID可以通过两个函数得到:
//jclass代表Java类,name表示成员函数或成员变量名,sig为这个函数的签名信息
jfieldID GetFieldID(jclass clazz, const char *name, const char *sig)
jmethodID GetMethodID(jclass clazz, const char *name, const char *sig)
得到这两个参数后,JNI层调用Java对象的成员变量和成员函数时,传入jfieldID 或jmethodID;jobject和其他参数就可以实现调用了。
JNIEnv与线程有关
JNIEnv是一个与线程相关的变量。
- 在JNI接口指针只在当前线程有效,一个本地方法不允许接口指针从一个线程到另
一个线程。实现JNI的虚拟机可以通过JNI接口指针向指针指向的区域分配和存储线程本地数据。 - 本地方法接收JNI接口指针作为实参。当它在同一个Java线程中对本机方法进行多次调用时,它保证会将相同的接口指针传递给本地方法。但是,可以从不同的Java线程调用本机方法,因此可以接收不同的JNI接口指针。
JNIEnv与JavaVM的区别
- JavaVM: JavaVM 是 Java虚拟机在 JNI 层的代表,JNI 全局只有一个
- JNIEnv: JNIEnv是JavaVM 在线程中的代表, 每个线程都有一个,JNI 中可能有很多个 JNIEnv
今日单词
- Class methods: 类的成员方法
- Class Fields: 类的成员变量
参考文章
- 《深入理解Android:卷1》
- Java中JNI的使用详解第二篇:JNIEnv类型和jobject类型的解释
网友评论