成都网站建设设计

将想法与焦点和您一起共享

android内核剖析系列---JNI调用机制分析-创新互联

为什么需要JNI?

创新互联公司-成都网站建设公司,专注网站设计制作、网站建设、网站营销推广,域名申请,网络空间,网站托管维护有关企业网站制作方案、改版、费用等问题,请联系创新互联公司

android这个庞大的系统从下到上主要由linux内核,C/C++库,java应用程序框架,java应用程序组成。这就涉及到一个问题,C/C++库如何与java应用有交集,或者说能相互调用,要解决这个问题,就需要JNI登场了。

JNI调用机制分析

JNI--java native interface,翻译成中文是java本地接口,所谓的“本地”是指C/C++库一层的C/C++语言(以下统称C)。

上文提到,JNI是为解决C和Java相互调用的问题而诞生的。C和Java相互调用无非就是两个方面,Java调用C和C调用Java。

Java调用C函数

如果你只定义了一个函数,而将它的实现交给C,那么就将它定义为native类型好了。你或许会问了,我用Java定义了一个函数,但我却没用Java实现之,当我调用这个函数的时候,Java编译器不会报错吗?答案是否定的,Java编译器在遇到native类型的函数时,不会关心该函数的具体实现,相当于native类型告诉Java编译器,“喂,老兄,我实现了,只不过我不是用你的语言(Java)实现的,我是用别的语言(C)实现的”,所以编译时Java编译器不会报错,只不过在调用native类型的函数前,程序员必须把C生成的动态库装载进内存,否则程序会因为找不到相应的native方法而出错。

Java和C本不是同种语言,硬要让它们能相互调用的话,我们就要遵循某种规范(就像ARM汇编和C相互调用时也要遵循某种规范一样)。

规范:methodname_C = Packagename + methodname_Java。什么意思呢?在C中定义的函数名称 = 包名 + 在Java中定义的函数名称。还不明白?我们来举个例子来看一下。

java:private nativefinal void init()

C:static void android_content_AssetManager_init(JNIEnv *env,jobject clazz)

可以看到对应的C函数多了两个参数,看起来莫名其妙,但这其实能让C访问Java对象或函数,JNIEnv对象是一个Java虚拟机所运行的环境,jobject是调用该函数的对象。我们稍后会讲到。

为什么C中的函数要加上包名呢?这不是多此一举吗?

这是有必要的,这是为了区分开不同包的两个同名函数,能够让Java编译器找到正确的那个函数。事实上,Java调用native函数时,编译器会向native引擎传递调用者的包名,以及函数名称,还有参数类型,以便可以根据这些信息找到正确的本地的那个函数。

C调用Java函数或者访问Java变量

正如Java调用C函数一样,Java把类名、函数名称和参数类型传递给native引擎,然后由native引擎处理(正确找到并调用)C函数。同理,C调用Java时,也需要把想要访问的类名、函数名称和参数传递给Java引擎。步骤如下:

1)获取Java对象的类

jclass cls = env->GetObjectClass(jobject),还记得env和jobject吗?没错,就是那两个参数。现在知道那两个参数的重要性了吧。不过,这也意味着C调用Java函数只能在Java调用C函数体中进行。

2)获取Java函数的id值

jmethodId mid = env->GetMethodId(cls,"methodname","(Ljava/lang/String;)V"),前两个参数不必说,第三个参数值得注意,它代表了Java函数的参数和返回值,参数在括号之中,返回值在括号之外。

3)找到了函数后,就可以调用该函数了

env->CallXXXMethod(jobject,mid,ret),其中XXX代表了返回值的类型,

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


网站标题:android内核剖析系列---JNI调用机制分析-创新互联
分享链接:http://chengdu.cdxwcx.cn/article/dghecd.html