《Android的设计与实现:卷I》——第2章2.4 在Java中调用JNI实现方法

2.4 在Java中调用JNI实现方法

本节介绍如何在Java中调用JNI实现方法、JNI数据类型转换、JNI方法命名规则,以及JNI方法签名规则。

2.4.1 Java数据类型与JNI数据类型转换

Java中调用Native方法传递的参数是Java类型的,这些参数需要经过Dalvik虚拟机转化为JNI类型才能被JNI层识别。下面分基本类型和引用类型介绍这种转化关系。

1.基本类型转化关系

表2-1列出了基本类型的转化关系。


2.引用类型转化关系

JNI的引用类型定义了九种数组类型,以及jobject、jclass、jstring、jthrowable四种类型。要理解其转化关系,首先要理解其继承关系。JNI引用类型的继承关系如图2-3所示。

JNI引用类型采用了与Java类型相似的继承关系。树根是jobject对象,其他所有自定义对象都可以用jobject表示。表2-2中列出了JNI引用类型和Java引用类型的转化关系。

2.4.2 JNI方法命名规则

Log系统中,JNI实现方法与Java声明方法是不同的。例如,Java层声明的Native方法名是isLoggable,而其对应的JNI实现方法的方法名却是android_util_Log_isLoggable。可见,除了数据类型有对应关系外,方法名也有对应关系。

JNI 接口指针是JNI实现方法的第一个参数,其类型是JNIEnv。第二个参数因本地方法是静态还是非静态而有所不同。非静态本地方法的第二个参数是对Java对象的引用,而静态本地方法的第二个参数是对其 Java 类的引用。其余的参数都对应于Java 方法的参数。
JNI规范里提供了JNI实现方法的命名规则,方法名由以下几部分串接而成:

2.4.3 JNI方法签名规则

有了数据类型之间的对应关系,JNI就可以正确识别并转换Java类型。那JNI又是如何识别Java的方法呢?

Java支持方法重载,仅靠函数名是无法唯一确定一个方法的。于是JNI提供了一套签名规则,用一个字符串来唯一确定一个方法。其规则如下:
(参数1类型签名参数2类型签名……参数n类型签名)返回值类型签名
以上签名字符串之间均没有空格。
类型签名又有一些规则,如表2-3所示。


注意 类的签名规则是:“L+全限定类名+;” 三部分组成,其中全限定类名以”/”分隔,而不是用“.”或者“_”分隔。

例如,Java 方法:
long fun (int n, String str, int[] arr);
其方法签名:
(ILjava/lang/String;[I)J
   括号里面的内容分成三部分,之间没有空格,即“I”、“Ljava/lang/String;”和“[I”,分别代
   表 int、String和int[]。括号外面是返回值类型签名,J代表long型。

回到Log系统的例子,JNINativeMethod结构体中第二个元素便是方法签名信息, 代码如下:
static JNINativeMethod gMethods[] = {
{ "isLoggable", "(Ljava/lang/String;I)Z",(void*)
android_util_Log_isLoggable },
{ "println_native","(IILjava/lang/String;Ljava/lang/String;)I",(void)
android_util_Log_println_native },
};

可以看出isLoggable函数有两个参数,一个是String类型,另一个是int类型,返回值为boolean类型。

至此,我们已经可以正确识别类型信息和函数信息。可如何操作对象并访问它们的成员变量和方法呢?下一节继续介绍。

时间: 2024-09-27 07:42:29

《Android的设计与实现:卷I》——第2章2.4 在Java中调用JNI实现方法的相关文章

handle-关于Android中调用了post方法后数据还是显示不出来的问题

问题描述 关于Android中调用了post方法后数据还是显示不出来的问题 Map params = new HashMap(); params.put(HZConstants.USER_TOKEN, HZApplication.get().getToken()); NetworkController.getInstance(mContext).drawperform(params,new NetworkCallBack() { @Override public void response(St

《Android游戏开发详解》一1.6 函数(在Java中称为“方法”更好)

1.6 函数(在Java中称为"方法"更好) Android游戏开发详解让我们将目前为止所学到的所有内容组合起来,并且讨论编程的一个重要方面,即函数. 函数是一组规则.特别地,函数应该接受一个值并且输出一个相应的结果.以一个数学函数为例. f(x)=3x +2 输入是任意的数值x,输出是3x +2的结果 例如,f(1)=3(1)+2=5 在Java中,我们可以定义一个非常类似的函数.如下的函数将接受一个float类型的输入,并且输出计算3x+2的结果. 程序清单1.6 Java函数 1

《Android的设计与实现:卷I》——第2章 2.5 JNI操作Java对象

2.5 JNI操作Java对象 JNI提供了Java和C/C++方法互操作的机制,上节只介绍了如何在Java中调用JNI实现方法,那JNI又是如何操作Java层呢?JNI方法接受的第二个参数是Java对象:jobject,可以在JNI中操作这个jobject进而操作Java对象提供的变量和方法. 2.5.1 访问Java对象 要操作jobject,就是要访问这个对象并操作它的变量和方法.JNI提供的类和对象操作函数有很多,常用的有两个:FindClass和GetObjectClass,在C和C+

Android UI设计系列之自定义ViewGroup打造通用的关闭键盘小控件ImeObserverLayout(9)_Android

转载请注明出处:http://blog.csdn.net/llew2011/article/details/51598682 我们平时开发中总会遇见一些奇葩的需求,为了实现这些需求我们往往绞尽脑汁有时候还茶不思饭不香的,有点夸张了(*^__^*)--我印象最深的一个需求是在一段文字中对部分词语进行加粗显示.当时费了不少劲,不过还好,这个问题最终解决了,有兴趣的童靴可以看一下:Android UI设计之<六>使用HTML标签,实现在TextView中对部分文字进行加粗显示. 之前产品那边提了这样

《Android的设计与实现:卷I》——第2章 框架基础JNI

第2章 框架基础JNI JNI(Java Native Interface,Java本地接口)是Java平台上定义的一套标准的本地编程接口.JNI允许Java代码与本地代码互操作,即Java代码可以调用本地代码,本地代码也可以调用Java代码.所谓本地代码指的是用其他编程语言(如C/C++)实现的.依赖于特定硬件和操作系统的代码.通过JNI调用本地代码,可以实现Java语言所不能实现的功能.在Android平台上,Dalvik虚拟机会实现JNI定义的接口. 2.1 JNI在Android系统中所

《Android的设计与实现:卷I》——第1章 1.6 NDK开发环境配置

1.6 NDK开发环境配置 Google官方对NDK(Native Development Kit,原生开发工具集)的解释如下: The Android NDK is a set of tools that allows Android application developers to embed native machine code compiled from C and/or C++ source files into their application packages. 可见,NDK

《Android的设计与实现:卷I》——第1章 2.2JNI框架层实例分析

2.2 JNI框架层实例分析 框架层大量使用了JNI技术来完成对系统运行库的调用.深入理解JNI对分析框架层代码十分有用.本节将以框架层的实例详细讲解JNI编程的三个步骤. 在Android应用程序开发中,一般是调用应用框架层的android.util.Log.java提供的Java接口来使用日志系统.比如我们会写如下代码输出日志: Log.d(TAG,"debug log"); 这个Java接口其实是通过JNI调用系统运行库(即本地库)并最终调用内核驱动程序Logger把Log写到内

《Android的设计与实现:卷I》——第3章 3.5触发并启动Action和Service

3.5 触发并启动Action和Service init解析init.rc后,生成了存放Service和Action的链表.那么init又是如何控制这些Action和Service的呢?本节将详细分析这部分内容. 3.5.1 触发Action init解析完init.rc后,接着执行了action_for_each_trigger和queue_builtin_action.这两个函数做了些什么呢? 首先定位到action_for_each_trigger,其实现代码位于init_parser.c

《Android的设计与实现:卷I》——第1章 1.3Android源码下载和编译

1.3 Android源码下载和编译 Android源码的开发需要Linux环境,读者可以安装Ubuntu 10.04及其后续版本,推荐安装Ubuntu的10.04或者12.04这两个LTS(长期技术支持)版本.本书基于Jelly Bean(Android 4.1)分析源代码,该部分源代码的编译需要64位操作系统环境.本节将介绍如何在Ubuntu 12.04(LTS)-64bit上搭建Android源码开发所需环境,这是保障后续步骤能够顺利进行的前提条件,必须准确无误.Android源码分成上层