李彬博客专栏

这是一个程序猿的天堂!

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

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端的数据类型对应如下表:

Tables Are
java jni
char jchar
byte jbyte
short jshort
int jint
long jlong
float jfloat
double jdouble
boolean jboolean

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类的构造方法可以制定堆栈的大小。

阅读更多
版权声明:转载请标明出处 http://blog.csdn.net/github_33304260 https://blog.csdn.net/github_33304260/article/details/62891137
文章标签: jni java android NDK so
个人分类: JNI
所属专栏: JNI
想对作者说点什么? 我来说一句

Android视频《JNI

-

学院

2016年10月28日 15:19

android jni教程

2012年03月15日 544KB 下载

Android底层开发jni_ndk视频教程

2017年10月30日 126B 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭