学习资料来源
《深入理解Android卷1》
JNI概述
全称为Java Native Interface。JNI是一种技术,可以做到:
1.Java程序中可以调用C/C++语言1写的函数
2.C/C++程序中可以调用Java层的函数
简单示意图:
形象的说,JNI就是一座桥梁,这座桥梁连接的是Native世界和Java世界。
实现步骤:
1.编写Java文件
2.编写头文件
3.编写C/C++文件
JNI动态库的命名
“动态库” 就是运行时加载的库,用MediaScanner做参考:
JNI动态库的命名一般为{module}_jni,如:media_jni。在实际加载时,linux平台会将其扩展为libmedia_jni.so,windows平台会将其扩展为media_jni.dll。示意图如下:
Java层分析
Java要想调用Native函数,只需做两个事情:
1.加载JNI库
2.声明并调用Java的native函数
native是java的关键字,用native命名的方法表示此方法将由JNI层完成,此处的native_init方法就是用native关键字定义的方法。
示例:
public class MediaScanner{
static{
System.loadLibrary("media_jni");//加载对应的JNI库
native_init();//调用native函数
}
......
private static nativa final void native_init();//声明native函数
......
}
Java要调用native函数,必须通过一个位于JNI层的动态库来实现。前面已经说过动态库就是程序运行的时候加载的库,具体是什么时候加载呢,在调用native函数前都可以。通行的做法是如上在静态代码块加载,即在static语句里调用System.loadLibrary方法。系统会根据平台自动扩展成真实库名,如Linux会扩展成libmedia_jni.so。
JNI层分析
Java层的 native_init() 对应的JNI层函数是 android_media_MediaScanner_native_init() 。
看上去JNI层的名字长了些,其实并没有,Java层的native_init的在android.media包里,完整路径为android.media.MediaScanner.native_init。“.”在native里有特殊意义,因此全换成了“_”。
这两个函数是通过“注册”关联起来的。注册的方法有两种:
1.静态方法
第一步:把Java代码编译成.class文件
第二部:用Javah命令2
原理:JNI层的工作是虚拟机做的,虚拟机保存了JNI层函数的指针,当调用Java层函数的时候,虚拟机使用对应函数指针找到该函数。
2.动态注册
有时间再看吧!
数据类型转换
JNI有自己的数据类型,不过能够与Java层的数据类型对应起来。不过所占字长可能有所不同。如:Java的char一般占一个字节,JNI的jchar占两个字节。部分对应关系如下:
Java层 | JNI层 |
---|---|
boolean | jboolean |
byte | jbyte |
char | jchar |
int | jint |
native层分析
通过JNIEvn可以实现native层代码的调用,也可以实现native层反调java,这里暂时没看懂。。。。。。
小结
此文对JNI的探讨非常浅显,有时间记得加强!!!