JNI学习(2)(我是菜鸟)-JNIEnv介绍

所有内容为记录学习过程,不是大牛尽情谅解。所有分析都参考深入理解Android 卷一


JNIEnv 是一个 与线程相关的代表JNI环境的结构体。(先记下,但是没明白)

JNIEnv 实际上提供了一些JNI系统函数,通过这些函数可以做到

1,调用java函数

2,操作jobject对象等很多事情

关于这个JNIEnv 还是不大明白但是继续看代码

通过JNIEnv 操作jobject

首先我们要了解操作jobject的实质是什么,一个java对象是由成员变量和成员函数组成,所谓的操作jobject的本质就应当是操作这些对象的成员变量和成员函数。所以应先看与成员变量和成员函数有关的内容。

1jfildID jmethodID 介绍

看这两个名字也知道 是成员变量的id  和 成员函数的id

JNI中规定用jfieldID jmethodID 来表示JAVA类的成员变量和成员函数

通过 JNIEnv 的下面两个方法得到 

jfieldID getFieldID(jclass clazz, const char *name , const char *sig)

jmethodID GetMethodID(jclass clazz, const char* name,const char*sig);

Jclass代表java类, name表示成员函数或者成员变量的名字,sig为这个函数和变量的签名信息

参考android_media_MediaScanner.cpp::MyMediaScannerClient 代码学习一下

JNI学习(2)(我是菜鸟)-JNIEnv介绍_第1张图片


对以上代码开始分析

60行 首先找到 android.media.MediaScannerClient类在JNI层中对应的jclass实例

65行 通过MediaScannerClient对象 取出里面的sanFile 函数的jmethodID

67行 通过MediaScannerClient对象 取出里面的handleStringTag 函数的 JmethodID

69 行 71 行一样的意义

并且将这些 jmethod 变量保存为MyMediaScannerClient 成员变量

为什么这里要保存呢,是因为 如果每次都通过env查询jmethodID 或者 jfieldID 的话 那么将影响程序的执行效率,所以在初始化的时候,就保存这种常用的方法的ID,以供后面使用。

那么 取出这些ID 后, 该如何使用呢?

看一下android_media_MediaScanner.cpp::MyMediaScannerClient::scanFile


JNI学习(2)(我是菜鸟)-JNIEnv介绍_第2张图片


通过JNIEnv 的 mEnv ->  CallVoidMethod 方法 再把 jobject jMethodID 和对应的参数传进去,JNI层就可以调用java对象的函数了!!

实际上JNIEnv输出了一系列的类似于CallVoidMethod的函数,形式如下

NativeType Call<type>Method(JNIEnv *env , jobject obj , jmethodID methodID, 函数参数。。。)

其中type 对应Java函数的返回值类型,例如CallIntMethod 等等

上面这种方法时针对于非static函数的,如果想要调用java中国女的static 函数,则用JNIEnv输出的CallStatic<Type>Method系列函数

下面了解一下如何通过JNIEnvjfieldID操作jobject的成员变量呢

//获取fieldID后 可以调用 Get<type>Field 系列的函数获取jobject对应的成员i按量,

NativeType Get<Type>Field(JNIEnv *env , jobject obj, jmethodID methodID)

或者通过Set<Type>Field系列函数 来改变jobject对应的成员比那两值

学到明白了jfieldID jmethodID的作用 也了解了该如何通过JNIEnv的函数来操作jobject

该文章来源于 深入理解Android 卷一,为我自己看书以后的测试篇



你可能感兴趣的:(java,jni)