《深入理解Android:卷1》- JNI层(二)

JNIEnv是什么?

《深入理解Android:卷1》- JNI层(一)中,在JNI函数的注册方法中,不管是静态方法还是动态方法,其函数参数中第一个参数是一个接口指针,类型为JNIEnv。

JNIEnv类型实际上代表了Java在本线程的运行环境,通过这个JNIEnv* 指针,就可以对Java端的代码进行操作。JNIEnv的指针会被JNI传入到本地方法的实现函数中来对Java端的代码进行操作。

JNIEnv内部结构和作用

JNIEnv是一个指向指针的指针,这个指针指向一个指针数组,指针数组中的每个指针指向接口函数。

《《深入理解Android:卷1》- JNI层(二)》 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: 类的成员变量

参考文章

    原文作者:Dufre
    原文地址: https://www.jianshu.com/p/584ea9afa0f1
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞