JNI,是Java Native Interface的缩写
· Java程序中的函数可以调用Native语言写的函数,Native一般指的是C/C++编写的函数。
· Native程序中的函数可以调用Java层的函数,也就是在C/C++程序中可以调用Java的函数。
java做的事
· 加载对应的JNI库。
· 声明由关键字native修饰的函数。
JNI做的事
. JNI层必须实现为动态库的形式,这样Java虚拟机才能加载它并调用它的函数。
. 注册JNI函数--之意就是将Java层的native函数和JNI层对应的实现函数关联起来
. 数据类型转换
.JNIEnv通过调用CallVoidMethod,CallIntMethod等调用Java对象
一、注册JNI函数
1、静态注册
· 先编写Java代码,然后编译生成.class文件。
· 使用Java的工具程序javah,如javah–o output packagename.classname ,这样它会生成一个叫output.h 的JNI层头文件。其中packagename.classname是Java代码编译后的class文件,而在生成的output.h文件里,声明了对应的JNI层函数,只要实现里面的函数即可。
关联关系,其实就是保存JNI层函数的函数指针。以后再调用native_init函数时,直接使用这个函数指针就可以了,当然这项工作是由虚拟机完成的。
2、动态注册
动态注册的工作,只用两个函数就能完成
.jclass clazz = (env)->FindClass(env, className);
. //调用JNIEnv的RegisterNatives函数,注册关联关系。
(env)->RegisterNatives(env, clazz, gMethods,numMethods);
当Java层通过System.loadLibrary加载完JNI动态库后,紧接着会查找该库中一个叫JNI_OnLoad的函数,如果有,就调用它,而动态注册的工作就是在这里完成的。
二、数据类型转换
在Java中调用native函数传递的参数是Java数据类型,那么这些参数类型到了JNI层会变成什么呢?
Java数据类型分为基本数据类型和引用数据类型两种
三、JNIEnv介绍
JNIEnv实际上就是提供了一些JNI系统函数。通过这些函数可以做到:
· 调用Java的函数。
· 操作jobject对象等很多事情。
1、jfieldID 和jmethodID的介绍
在JNI规则中用jfieldID 和jmethodID 来表示Java类的成员变量和成员函数通过JNIEnv的下面两个函数可以得到:
jfieldID GetFieldID(jclass clazz,const char*name, const char sig);
jmethodID GetMethodID(jclass clazz, const charname,const char *sig);
2、使用jfieldID和jmethodID
JNIEnv通过调用CallVoidMethod,CallIntMethod、CallStatic等再把jobject、jMethodID和对应参数传进去,JNI层就能够调用Java对象的函数了