Android测试需要get的知识——JNI - 51ste软件测试部落-中国软件测试者的乐园
登录|注册

Android测试需要get的知识——JNI

作者:smart  发布时间:2018-05-16 13:05:57  关键字:JNI Java原生接口 

一、前言

JNI—Java与底层间的桥梁,Android系统中很多的使用了JNI,小编所在项目中核心模块有相关调用。测试中,也有遇到过JNI层的一些问题。理解JNI的调用实现,对于理解Android的代码有帮助。

二、JNI简介

1、概念介绍

JNI是Java Native Interface的简写,可译作Java原生接口。JNI是Java本地调用接口,所谓的Native是调用C/C++的程序。

2、JNI应用场景

1)调用驱动(Java无法处理):需要用到Java标准平台不具备的依赖于操作系统的特性时。由于操作系统提供的驱动一般都是C接口,Java语言并不具备操作这些驱动的能力;

2)对性能要求比较高或对时间敏感,有必要用更底层的语言:Java可以通过JNI调用C/C++的库,对于计算量比较大,处理数据比较多的模块,Java的效率没有C高,所以希望用C去完成;

3)对于某些功能模块,可能Java和C的效率差不多,已经有现成的,用其他语言已经完成的功能时,需要用Java去直接调用,不用Java重写了。

三、JNI技术的原理

在Java程序中调用C/C++程序是通过JNI技术实现的。JNI技术的原理是,在Java源码中声明一个空的特殊函数,Java虚拟机在碰到这个函数时,会加载C/C++程序库,并定位到相应的函数执行其代码。

1、调用过程示意

Android测试需要get的知识——JNI

2、通常执行步骤

1)编写带有native声明的方法的java类;

2)使用javac命令编译所编写的java类(class文件),然后使用javah+java类名将上步中的class文件生成扩展名为h的头文件;

命令:javah–jni×××

Javah程序统一了Java中的native方法,头文件中的函数名和动态库中的函数实现之间的对应关系。

3)用其他语言(C/C++)实现上述头文件中的函数;生成动态链接库,供Java程序使用;

4)发布Java和动态库;

JNI对于应用本身来说,可以看作一个代理模式。对于开发者来说,需要使用C/C++来实现一个代理程序(JNI程序)来实际操作目标原生函数,Java程序中则是jvm通过加载并调用此JNI程序来间接地调用目标原生函数。

四、JNI调用

JNI技术,它是一种双向的接口,使得开发者可以通过Java代码调用到各种native的库,反之亦然。简单来说,JNI可以实现Java调用C/C++,同时C/C++也可调用Java。

Java访问C/C++

Java如何调用C/C++的呢?在调用之前java是不会关心是否已经实现,只有在调用native方法的时候,去找C生成的动态库,如果找不到动态库,那么native方法就会报错。

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

比如,Framework中AssetManager类的成员函数init是一个JNI函数:

private native final void init();

它是由C++层的函数android_content_AssetManager_init来实现的:

static void android_content_AssetManager_init(JNIEnv*env,jobject obj){…}

在C中的规则就是,包名+类名+方法名,并且中间用下划线分割。

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

第二个参数jobject是调用该函数的对象,上面的例子指的就是AssetManager对象;每个这样的C函数的参数至少有这两个参数,如果native函数里有多个参数,依次在后面排列,java的数据类型和JNI中的数据类型对应关系。

当java调用native函数时,编译器会向native引擎传递调用者的包名,函数名及参数类型,native引擎根据这些信息决定应该调用具体的的哪个函数。

在android中,native引擎中的AndroidRuntime类提供了一个registerNativeMethods()函数,通过此函数定义java方法和C函数的映射关系。

C/C++访问java

C访问java,监听回调中常有使用。

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

java访问c的时候,把类名,函数名,参数类型传递给native引擎,然后由native引擎处理C函数,同理,C调用java时,也需要把想要访问的类名、函数名、参数传递给java引擎。

五、Android中的*.SDK

本文由51ste.com网友编辑,未经授权,不得转载使用上述作品盈利;个人转载,需标明原文作者及出处。

说说看法查看全部评论(0)

微信二维码

部落微信公众号

QQ二维码

部落QQ群二维码