前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android的JNI【实战教程】1⃣️--java和c/c++的那些事

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

作者头像
先知先觉
发布2019-01-21 11:26:24
8990
发布2019-01-21 11:26:24
举报
文章被收录于专栏:伟大程序猿的诞生

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()方法。

代码语言:javascript
复制
    static {
        System.loadLibrary("MyJni");
    }

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

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

代码语言:javascript
复制
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函数的调用。

代码语言:javascript
复制
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类的构造方法可以制定堆栈的大小。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017年03月17日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JNI的作用
  • JNI的用法
    • 从java到c/c++
    • ART带来的JNI变化
      • 垃圾回收的影响
        • 错误处理的变化
          • 堆栈可能引发的问题
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档