JNI简介
http://www.jianshu.com/p/aba734d5b5cd
函数注册
实例
java
1 | public class AndroidJni { |
C++
1 | #include <jni.h> |
要完成的任务是将java中声明的函数和C++中定义的函数链接起来。
静态注册native函数
模版:
JINEXPORT+返回类型+JNICALL+以_连接的java类作为函数名(JNIEnv* evn, jobject obj){}
JNIEXPORT和JNICALL关键字,这两个关键字是两个宏定义,他主要的作用就是说明该函数为JNI函数。java虚拟机加载so时会将检查到的带宏定义的函数,根据函数名链接到对应类的对应native函数。
javah -d jni (package)
动态注册native函数
当我们使用System.loadLibarary()方法加载so库的时候,Java虚拟机就会找到这个函数并调用该函数,因此可以在该函数中做一些初始化的动作,其实这个函数就是相当于Activity中的onCreate()方法。该函数前面有三个关键字,分别是JNIEXPORT、JNICALL和jint,其中JNIEXPORT和JNICALL是两个宏定义,用于指定该函数是JNI函数。jint是JNI定义的数据类型,因为Java层和C/C++的数据类型或者对象不能直接相互的引用或者使用,JNI层定义了自己的数据类型,用于衔接Java层和JNI层,至于这些数据类型我们在后面介绍。这里的jint对应Java的int数据类型,该函数返回的int表示当前使用的JNI的版本,其实类似于Android系统的API版本一样,不同的JNI版本中定义的一些不同的JNI函数。
so加载
System.loadLibarary()
1 | public static void loadLibrary(String libName) { |
loadlibrary()
1 | void loadLibrary(String libraryName, ClassLoader loader) { |
http://blog.sina.com.cn/s/blog_4c0706560102vc6o.html
loadLibrary -> nativeLoad(即Dalvik_java_lang_Runtime_nativeLoad) -> dvmLoadNativeCode -> dlopen\dlsym
最终通过dlopen函数完成的,只是本地库加载完后紧接着会查找库中是否有JNI_OnLoad函数,如果有会执行一下。
dvmLoadNativeCode()这个函数还真的是有点复杂,那就挑那些跟我们的JNI比较紧密相关的逻辑来看吧。可以认为这个函数做了下面的这样一些事情:
- 调用dlopen() 打开一个so文件,创建一个handle。
- 调用dlsym()函数,查找到so文件中的JNI_OnLoad()这个函数的函数指针。
- 执行上一步找到的那个JNI_OnLoad()函数。
http://blog.csdn.net/dj0379/article/details/53350038
注册函数
先看JNI_OnLoad方法,这是注册native函数的地方。
- 首先判断jni版本是不是JNI_VERSION_1_4
- FindClass方法找到我们对应生命native函数的类,返回一个jclass
- RegisterNatives 注册native函数,我这里用这个三个参数的方法,第一个表示对应jclass,第二个表示JNINativeMethod的数组,第三个,这个就是我们先前命名的宏。
JNINativeMethod数组
对应结构体
1 | typedef struct { |
JNINativeMethod nativeMethod[] = {{"dynamicLog", "()V", (void*)nativeDynamicLog},};```
* 第一个参数对应的native方法名
* 第二个参数对应 native方法的描述,我们通过javap -s class文件路径来获取。
* 第三个参数对应的是c++代码里对应的实现
RegisterNatives函数
* 第一个参数是Java层对应包含native方法的对象(这里就是AndroidJni对象),通过调用JNIEnv对应的函数获取class对象(FindClass函数的参数为需要获取class对象的类描述符)
* 第二个参数是JNINativeMethod结构体指针,这里的JNINativeMethod结构体是描述Java层native方法的,也就是之前定义的数组
* 第三个参数为注册native方法的数量。一般会动态注册多个native方法,首先会定义一个JNINativeMethod数组,然后将该数组指针作为RegisterNative函数的参数传入
描述符
对应smail语法
JNIEnv
[http://blog.csdn.net/banketree/article/details/40535325](http://blog.csdn.net/banketree/article/details/40535325)
## java和native之间的数据传递
[http://blog.csdn.net/qinjuning/article/details/7607214](http://blog.csdn.net/qinjuning/article/details/7607214)