您的位置:首页 > 移动开发 > Android开发

Android的JNI【实战教程】1⃣️--java和c/c++的那些事

2017-03-17 20:11 232 查看
JNI在Android和c/c++中起着重要的作用,就相当于桥梁。你知道抗日时候为啥要先炸桥梁就知道JNI在其中的重要性了。

JNI的作用

JNI是Java Native interface的缩写。JNI不是安卓特有的,是从Java继承过来的,但是在Android中,JNI的作用大大增强了。就好比火药是中国发明的,外国继承了火药发明了导弹一样。

Android作为嵌入式操作系统,有大量和驱动,硬件有关的功能必须在native实现,另外一些注重性能,功耗的功能用c/c++也要优于java

在Android中,java主要负责UI功能的实现,而c/c++则负责完成一些复杂的算法及底层的交互功能,因此Android中java和c/c++交互特别的频繁。所以有的人说android开发就是做java的,真的是很可怕的想法。

无论Java到c/c++,还是c/c++到java 中间都没有跨线程调用,两者在一个线程中,只是两者的线程id表示不同而已。java层的线程id从1开始,c/c++层实用的是一个与线程相关的数据结构的指针,两者不能比较。

JNI的用法

从java到c/c++

1. 装载JNI动态链接库

为了使JNI在本地方法调用前吧c/c++代码所在动态库装载待进程的内存空间中,装载库文件调用的是System的LoadLibrary()方法。

static {
System.loadLibrary("MyJni");
}


这里出入的参数只是动态库的文件名一部分。

Android JNI动态库的名称必须以”lib”开头, 这里传入的参数去掉了前缀”lib”和”.so”的中间部分。

2.定义native方法

在java类中定义narive方法很简单,在前面加上“native”关键字就行了,

public static native String getStringFromNative();


3.编写JNI动态库

JNI动态库和非动态库区别:JNI动态库中定义了一个名为“JNI OnLoader”的函数,这个函数在动态库加载后被系统调用,用于完成JNI函数的注册。在JNI_OnLoader函数中,最重要的一件事就是调用registerNativeMethods ()函数完成动态库中JNI函数的注册,所谓注册,就是通过一张表把java类中定义的native方法和本地C函数联系起来,这样Dalvik虚拟机在解析java类中的native方法是境内查找到对应的C函数

4.参数签名

为什么会有方法签名这种东西呢?这是因为Java这边支持函数重载,即虽然参数不一样,但是方法名一样,那么在JNI层它们的方法名都会是一样的,那JNI也会犯迷糊了,得找哪个呢?

不过也正是因为其参数类型是不一样的,所以就出现了方法签名,利用方法签名和方法名来唯一确定一个JNI函数的调用。

typedef union jvalue {
jboolean    z;
jbyte       b;
jchar       c;
jshort      s;
jint        i;
jlong       j;
jfloat      f;
jdouble     d;
jobject     l;
} jvalue;


签名由参数和返回值组成:

例如: (I)V 表示 有一个整型参数,无返回值

(IZ)I 表示 两个参数,第一个整型,第二个布尔型,返回整型

图解签名:



5.如何使用JNI类型

在JNI中,提供了以下各种数据类型,可以分为原生类型和引用类型: 对于原生类型有:jchar, jbyte, jshort, jint, jlong, jfloat, jdouble, jboolean,其与java端的数据类型对应如下表:

TablesAre
javajni
charjchar
bytejbyte
shortjshort
intjint
longjlong
float jfloat
double jdouble
booleanjboolean

ART带来的JNI变化

垃圾回收的影响

ART中的垃圾回收算法将回移动对象在内存中的位置。这样目的是为了减少内存碎片,提高内存使用率。这会java没太大影响,但是对JNI就要注意,不要试图通过指针方式直接访问函数分配的对象。

我们知道JNI使用和释放java层传递的数组参数要通过
Get..ArratElement()
Release…ArratElement()
两组函数完成的。在Dalivk中,
Get..ArratElement()
函数返回的是数组元素实际的内存引用,但是在ART中,这个函数返回的是数组元素的复制。

错误处理的变化

ART中JNI函数会抛出“异常”,而Dalivk中之时返回NULL。

堆栈可能引发的问题

在Dalivk中,java和native代码使用的不同的堆栈,大小也不同,java大小32kb,native大小1MB。

在ART中,native带啊使用相同的堆栈。

在Java代码中,Thread类的构造方法可以制定堆栈的大小。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jni java android NDK so