文档章节

JNI调用机制

henry-zhang
 henry-zhang
发布于 2015/05/27 10:58
字数 1459
阅读 89
收藏 12

JNI的简单介绍

 

Java Native Interface (JNI)是java本地调用接口,所谓的native就是调用c/c++的程序。

java调用C语言的情况一般有三种:

调用驱动。由于操作系统提供的驱动一般都是C接口,Java语言并不具备操作这些驱动的能力。

对于计算量比较大,处理数据比较多的模块,java的效率没有C高,所以希望用C去完成。

对于某些功能模块,可能Java和C的效率差不多,但是C已经写好了,就不想用Java重写了。

从程序的角度来说,主要关注两种情况:

java访问C

C访问java

对于理解JNI的调用实现,对于理解Android的源码有帮助,因为Android系统中大量的使用了JIN。

 

Java访问C

 

    任何语言直接的交互都必须遵循一定的规则或者协议,只有这样双方才能理解各自的意图。

java中定义native函数,对于native函数只需要声明,具体实现由C去实现。也就是说,native函数的

实现与声明是分离的,java负责声明,C负责实现。所以java在编译是不会关心具体实现,编译时就不会出错。

 

    如何调用的呢?在调用之前java是不会关心是否已经实现,只有在调用native方法的时候,去找C生成的动态库,如果

找不到动态库,那么native方法就会报错。

 

   java如何找到C的函数的呢?

 

    java的native函数和C中的函数存在一种映射关系,这个映射关系就是遵循的一种协议或者称为规则。

    比如,Framework中AssetManager类中声明了:

    

    private native final void init()

 

    该方法在C中对应的是:

   

   static void android_content_AssetManager_init(JNIEnv* env, jobject clazz)

 

   从上面的对应关系可以看出,在C中的规则就是,包名+类名+方法名,并且中间用下划线分割

   第一个参数env,是JNIEnv对象,该对象代表一个Java虚拟机所运行的环境,通过它可以访问JVM内部的各种对象;

    第二个参数jobject和是调用该函数的对象,上面的例子指的就是AssetManager对象;每个这样的C函数的参数至少

    有这两个参数,如果native函数里有多个参数,依次在后面排列,java的数据类型和JNI中的数据类型对应关系,

自己可以去网上查询一下。

 

   当java调用native函数时,编译器会向native引擎传递调用者的包名,函数名及参数类型,native引擎

根据这些信息决定应该调用具体的的哪个函数。

 

在android中,native引擎中的AndroidRuntime类提供了一个registerNativeMethods()函数,通过此函数

定义java方法和C函数的映射关系。

 

生成 .h文件

 

java 的native方法和JNI中的c中的函数的对应的定义文件头文件(.h文件)可以手工写,有些麻烦

并且还容易出错,java提供了一个javah工具,通过该工具可以从一个java文件自动生成相应的

投文件,网上查询一下具体用法。

    

接下来就是根据头文件去实现相应的C代码,然后生成动态库。

 

如果想在java中调用native方法,需要使用在调用的代码前面使用System.loadLibrary("lib_name")去

装载该动态库。

 

 

C访问java

 

  虽然C访问java的情况不多见,不过也是能遇到的。

 

 由于java中的函数在native引擎中并没有直接的函数指针,java函数只能由java引擎去执行,而不是C。所以访问

java不能通过指针,只能通过参数接口。

 

 java访问c的时候,把类名,函数名,参数类型传递给native引擎,然后由native引擎处理C函数,同理,

C调用java时,也需要把想要访问的类名、函数名、参数传递给java引擎。

 

按照如下步骤:

 

获取java对象的类

jclass cls = env->GetObjectclass(jobject);

jobject就是需要调用的谁的方法,java对象在JNI中的表示。

获得java方法的Id值

jmethodId mid = env->GetMethodId(cls, "method_name", "([Ljava/lang/String;)V");

第一个参数是java对象对应的类

第二个参数是java中的方法名称

第三个参数是数据类型和返回值

解释一下第三个参数:

参数在括弧中,返回值在括弧外, ([Ljava/lang/String;)V" : [Ljava/lang/String代表参数类型,如果是类包名用

“/”分开,并且前面加上又给大写的L。

java和native数据类型对应表

java类型 native类型

boolean Z

byte B

char C

double D

float F

int I

long L

Object 'L' + '包名'+';'

short S 这个参数可以自己手工写,还是那样容易出错,java提供了一个工具用来查看参数签名,使用javap工具可以自动生成,自己从网上查询一下即可。

调用函数

env->CallXXXMethod(jobject, mid, ret);

 

其中XXX是不同的类型,包括:Void,Oject,Boolean,Byte,Char,Short,Int,Long,Float,Double

第一个参数是调用的类的对象

第二个参数是上一步获得的方法的id

第三个参数数是返回值

上面是调用方法,调用java的变量也类似:

 

获取java对象的类

jclass cls = env->GetObjectclass(jobject);

获得变量的id

jfiledId fid = env->GetFiledId(cls, "fileName", "I");

获取变量值

value = env->GetXXXField(env, jobject, fid);

 

在C中使用持久对象和保持持久对象

 

 C中本身无法保存持久对象,把持久对象保存到一个int类型的变量上,使用的时候再强制转型成对象。


本文转载自:

henry-zhang
粉丝 2
博文 62
码字总数 1431
作品 0
海淀
私信 提问
JNI_OnLoad函数不存在的问题

今天分析一个app的老版本时,无意发现JNI_OnLoad不存在,但是so的确是java层load加载,各native函数也有声明和调用,以为又遇到什么黑科技。查找发现最早期的ndk开发版本中的确是没有这个函数...

kingsOSZT
2015/10/27
1K
0
Bluedroid的结构和代码分布

在android4.2中,Google更换了android的蓝牙协议栈,从Bluez换成Bluedroid,我也是初涉这个方面,顺便记录一下。 http://source.android.com/devices/bluetooth.html android development对于...

sflfqx
2014/08/12
932
0
android app中使用JNI

JNI提供了一种机制,使得在Java 代码中可以使用 C/C++ 的本地层代码,这种使用主要是指在 Java 代码中调用 C/C++ 代码。这种机制为我们开启了一扇门,一扇将Java 代码与广阔的 C/C++ 本地层连...

WolfCS
2013/03/02
4.2K
1
JNI Crash:异常定位与捕获处理

关键词:JNI Crash,异常检测,信号量捕获 在Android JNI开发中,经常会遇到JNI崩溃的问题,尤其带代码量大,或者嵌入了第三方代码的情况下,很难进行问题定位和处理。本文将介绍两种常见的J...

JackMeGo
2018/07/06
0
0
Android Camera 调用流程总结

1.总体介绍 Android Camera框架从整体上看是一个client/service架构。有两个进程,一个是client进程,可以看成AP端 ,主要包括Java代码和一些native层的c/c++代码;另一个是service进程,属于...

天王盖地虎626
06/21
21
0

没有更多内容

加载失败,请刷新页面

加载更多

只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

统一返回值 在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。 比较通用的返回值格式如下:...

晓月寒丶
昨天
59
0
区块链应用到供应链上的好处和实际案例

区块链可以解决供应链中的很多问题,例如记录以及追踪产品。那么使用区块链应用到各产品供应链上到底有什么好处?猎头悬赏平台解优人才网小编给大家做个简单的分享: 使用区块链的最突出的优...

猎头悬赏平台
昨天
28
0
全世界到底有多少软件开发人员?

埃文斯数据公司(Evans Data Corporation) 2019 最新的统计数据(原文)显示,2018 年全球共有 2300 万软件开发人员,预计到 2019 年底这个数字将达到 2640万,到 2023 年达到 2770万。 而来自...

红薯
昨天
65
0
Go 语言基础—— 通道(channel)

通过通信来共享内存(Java是通过共享内存来通信的) 定义 func service() string {time.Sleep(time.Millisecond * 50)return "Done"}func AsyncService() chan string {retCh := mak......

刘一草
昨天
58
0
Apache Flink 零基础入门(一):基础概念解析

Apache Flink 的定义、架构及原理 Apache Flink 是一个分布式大数据处理引擎,可对有限数据流和无限数据流进行有状态或无状态的计算,能够部署在各种集群环境,对各种规模大小的数据进行快速...

Vincent-Duan
昨天
60
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部