转载自
http://blog.csdn.net/banketree/article/details/12167145
JNI是联通Java和C/C++的机制
JNI(Java Native Interface)就java语言提供的java和C/C++相互沟通的机制,java可以通过jni调用本地的C/C++代码,本地的C/C++也可以调用java代码。JNI是本地编程接口,java和C/C++互相通过的接口。Java通过C/C++使用本地的代码的一个关键性原因在于C/C++代码的高效性。
NDK 是一组工具
NDK是一系列工具的集合。它提供一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。它集成了交叉编译器,提供了相应的mk文件隔离cpu,平台,ABI等差异,开发人员只需要简单修改mk文件(指出 哪些文件须编译,需要依赖哪些库,编译特性等要求),就可以创建出so。它可以自动地将so和java应用一起打包。
java通过jni机制和C/C++沟通的具体步骤
1,编写包含native本地方法的java类
2:,通过javah工具生成C/C++语言的文件
3,使用C、C++语言实现头文件
4,使用交叉编译工具对C/C++本地代码进行编译,最后通过链接生成so可执行的C/C++库。
5,实际执行java代码去和本地的C/C++代码沟通
JNI中的JavaVM和JNIEnv对象
Android平台上,每个process只能产生一个DalvikVM对象,也就是说每个Android进程通过有且只有一个虚拟机对象来服务所有的java和C/C++代码。
1:JNIEnv* 内部包含一个Pointer,Pointer指向DalvikVM的javaVM对象的function table,JNIEnv* 关于程序执行环境的众多函数正是来自于Dalvik虚拟机。
2:Android中每当一个java线程第一次要调用本地C/C++代码时,Daavik虚拟机实例会为该java线程产生一个JNIEnv指针。
3,java每条线程和C/C++互相调用时,JNIEnv*是相互独立的,互不干扰
4,本地的C/C++代码想要获得当前线程所要使用的JNIEnv时,可以使用Dalvik VM对象的javaVM* jvm->getEnv()方法,该方法返回当前线程所在的JNIEnv*。
1、java的dex字节码和C/C++的*.so同时运行DalvikVM之内,共同使用一个进程空间。每次使用jni调用c/c++开辟一个线程去处理
2、java和C/C++可以相互调用,调用的关键是DalvikVM
3、一般而言,比较经典的模式是Java通过JNI的C组建和C++相互沟通,一般业务处理放在C/C++中
4、C++代码处于核心控制地位更具价值
java调用C/C++代码时
DalvikVM虚拟机中加载动态链接库,会先调用JNI_Onload()函数,此时会把javaVM对象的指针存储在C层JNI组件的全局环境中
java层调用c层的本地库函数时,调用C本地函数线程必然通过Dalvik VM来调用C本地函数,Dalvik VM会为本地C组件实例化一个JNIEnv指针,该指针执行Dalvik虚拟机
的具体函数列表,当JNI C组件调用java方法和属性时,需要通过JNIEnv指针进行调用。
C/C++组件调用java时
需要通过JNI的C组件把JNIEnv指针传递给C++组件,此后C++组件既可以通过JNIEnv指针来调用java层代码。
总结
JNI是java调用的native机制,是java自身的语言特性全程java native interface ,所以说JNI和android没有关系。在pc上开发java应用,运行在windows平台 jni是经常使用的。
NDK是google公司推出的帮助android开发者通过C/C++本地语言编写应用的开发包。
简单点说,用C/C++语言生成一个库文件,在java中调用这个库文件的函数。JNI的过程比较复杂,生成so需要大量的操作,而NDK就是简化了这个过程。