JNI初步

来源:互联网 发布:马尔可夫链矩阵 编辑:程序博客网 时间:2024/04/29 10:57

不知道为什么,对JAVA一直有些反感,说来都奇怪,几乎不了解jAVA,估计是八字不合。

移动平台,IOS和android基本两分天下了。同一个应用必须提供两个版本也几乎成为客户的必选要求。但通信和数据库等操作又几乎完全是相同的。那么对于重复的这块当然不能重复劳动。这就需要提供一套代码供object-c和java通用。这个选择就呼之欲出了:C/C++代码。object-c可以直接使用C/C++源码或者库,而java就必须通过JNI调用C/C++库。


记录点关于JNI的东西,本篇是初步的。


Java是解释型语言,经过java编译器生成的是java字节码,它是JVM的输入,而解释器集成在了JVM之中。虽然JAVA可以做到JIT编译或者各种其他优化,但是这个步骤不是java编译器做的事情,其发布依旧是字节码,那么终究跳不出解释型语言范畴。

JAVA的一大关键是JVM,它是java程序运行的环境。JVM实例是进程级的,对应于每个java程序;而JVM引擎实例对应线程级的一个命令流。

JVM的内部体系结构分为:1、类装载器子系统,用来装载.class文件。2、执行引擎,执行字节码或者本地方法。3、运行时数据区,包括方法区、堆、java栈、pc寄存器、本地方法栈


JNI,Java Navtive Interface。Java编译结果和发布代码都是java code的中间码,这在跨平台时拥有很好的灵活性。可是面对众多的已经存在的C/C++代码或者应效率要求使用C/C++编写的代码时却没法直接享受了。那么JNI就是为了解决这个问题的技术,它可以让你的java代码享受海量的已经存在的C/C++代码库。


JNI既然是一种接口,那就跳不脱约定的双方和双方的交互。约定的双方就是java程序和本地代码(c/c++代码)。而对于交互的约定如下:

1、在java程序中需要声明供java使用的函数,除了加个关键字以外跟声明原生的java函数一样。关键字是native,代表这个函数的实现交给本地代码。同时需要指定加载哪一个二进制库,也就是说实现所在的库的名字。

package com.test.test1;public class HelloWorld {static {System.loadLibrary ( "hello_jni" ) ;}public native int process ( String method);}
2、根据这个java接口的.class生成相应的本地代码的头文件,也就是说两个约定要一致,这个一致由javah定义,jni实现。


需要进入java项目放.class的根目录/classes中,然后运行javah -classpath . com.test.test1.HelloWorld然后会生成一个com_test_test1_HelloWorld.h的c/c++头文件。这样在编写c/c++代码时按照这个头文件的声明进行就ok了。1中的native函数通过javah生成如下本地代码的声明:JNIEXPORT jint JNICALL Java_com_test_test1_process(JNIEnv *, jstring)

3、本地代码实现的库名字与java代码loadLibrary的对应上,其实貌似没必要在实现的c++代码去调用


registerNativeMethods因为按照javah生成的头文件的名称,jni相关机制可以保证映射了。


最后在c/c++实现的代码中,很多精力需要放在Jni类型和c/c++类型的转换。


初步的记录先这样了。之后逐渐使用会比较多的描述下3方面的东西以及其他。