Android 框架基础 -JNI

本贴最后更新于 3081 天前,其中的信息可能已经事过景迁

1.NDK 与 JNI 的区别:

NDK 是为了方便开发基于 JNI 的应用而提供的一套开发和编译工具集;

JNI 是一套编程接口,可以运用在应用层,应用框架层,用以实现 Java 代码与本地代码的交互。

2.编程的模型结构:

第一步:Java 层声明 Native 方法。

第二步:JNI 层实现 Java 层声明的 Native 方法,在 JNI 层可以调用底层库或者毁掉 Java 层方法。

第三步:加载 JNI 层代码编译后生成的共享库。

JNI 中的 JNIEnv 是什么:

在 C++ 中:JNIEnv 就是 struct_JNIEnv。JNIEnv* env 等价于 struct _JNIEvn* env,在调用 JNI 函数的时候,只需要 env->FindClass(JNIEnv*,const char*),就会间接调用 JNINativeInterface 结构体里定义的函数指针,而无需先对 env 解引用。

在 C 中:JNIEnv 就是 const struct JNINativeInterface*.JNIEnv* env 实际等价于 const struct JNINativeInterface** env,因此要先解引用得到 env,才能调用到 JNINativeInterface 结构体里面定义的函数指针。解引用调用方法即(env)->FindClass(JNIEnv,const char)。

注意:JNIEnv 只在当前现成合纵有笑。本地方法不能将 JNIEnv 从一个现成传递到另一个现成中。相同的 java 现成中对本地方法多次调用的时候,传递给该本地方法的 JNIEnv 是相同的。但是一个本地方法可以被不同的 Java 现成所调用,因此可以接受不同的 JNIEnv。

第一节 在 Java 中调用 JNI 实现方法

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

(Java 层调用 JNI 方法传递参数是 Java 类型需要通过 dalvik 虚拟机转换后才能被 JNI 识别。)

Java-JNI 基本数据类型转换关系表
| Java 类型 | JNI 类型 | 字 长 |
| boolean | jboolean | 8 位 |
| byte | jbyte | 8 位 |
| char | jchar | 16 位 |
| short | jshort | 16 位 |
| int | jint | 32 位 |
| long | jlong | 64 位 |
| float | jfloat | 32 位 |
| double | jdouble | 64 位 |
| void | void | |
| | | |

JNI 方法命名规则:

Java_前缀

全限定的类名

下划线(_)分隔符

增加第一参数 JNIEnv* env

增加第二个参数 jobject

其他参数按类型映射

返回值按类型映射

例如:

public static native boolean isLoggable(String tag, int level);

对应的 JNI 方法实现:

static jboolean android_util_Log_isLoggable(JNIEnv* env,jobject clazz,jstring tag,jint level){//...实现代码};

在框架层中可以采用函数注册的方式建立 Java 层生命方法与 JNI 层实现方法之间的对应关系,可以不遵守这些规则。

JNI 方法签名规则:(用一个字符来识别重载方法)


JNI 类型签名规则
| Java 类型 | 类型签名 | Java 类型 | 类型签名 |
| boolean | Z | long | J |
| byte | B | float | F |
| char | C | double | D |
| short | S | 类 | L 全限定类名; |
| int | I | 数组 | [元素类型签名 |

例如:

long fun(int n , String str,int[] arr);

对应的方法签名:

(ILjava/lang/String;[I)J

JNI 操作 Java 对象(通过操作 jobject 带来操作 Java 对象提供的变量和方法):

FindClass 和 GetObjectClass

在 C++ 中:

jclass FindClass(const char* name);//查找类信息

jclass GeObjectClass(jobject obj);//返回对象的类

在 C 中:

jclass (FindClass)(JNIEnv ,const char*);

jclass (GetObjectClass)(JNIEnv , jobject);

注意:通过 FindClass 传入要查找的类的全限定名(以“/”分隔路径)即可,之后方法返回一个 jclass 对象,这样就可以操作这个类的方法和变量了。

操作成员变量(域)和方法:

Java 中习惯将变量成为成员变量,而不是域。为了兼容 JNI 命名规则和 Java 习惯,将域和变量等价。

操作变量=》以 Log 系统为例:

第一步:通过 FindClass 方法找到类的信息 clazz;

第二步:以 clazz 为参数调用 GetStaticFieldID(clazz,"DEBUG","I");其中 DEBUG 是要访问的 Java 域的名字,I 是该域的类型签名,即整型。

第三步:GetStaticFieldID 函数返回一个 jfieldID,代表 Java 成员变量。最后将该 ID 传给 GetStaticField 方法,得到 Java 层的成员变量 DEBUG 的值。

操作方法:

与操作成员变量类似,流程如下:

FindClass->GetMethodID(返回 jmethodID)->CallMethod

其中 Type 为方法的修饰符,如 public ,private 等等

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 563 关注
  • JRebel

    JRebel 是一款 Java 虚拟机插件,它使得 Java 程序员能在不进行重部署的情况下,即时看到代码的改变对一个应用程序带来的影响。

    26 引用 • 78 回帖 • 683 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    246 引用 • 1338 回帖
  • 招聘

    哪里都缺人,哪里都不缺人。

    188 引用 • 1057 回帖
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 62 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    229 引用 • 476 回帖 • 1 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 68 关注
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    17 引用 • 7 回帖 • 1 关注
  • CentOS

    CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise Linux 依照开放源代码规定释出的源代码所编译而成。由于出自同样的源代码,因此有些要求高度稳定的服务器以 CentOS 替代商业版的 Red Hat Enterprise Linux 使用。两者的不同在于 CentOS 并不包含封闭源代码软件。

    240 引用 • 224 回帖
  • WebClipper

    Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。

    3 引用 • 9 回帖 • 1 关注
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    730 引用 • 1283 回帖
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    346 引用 • 760 回帖
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    29 引用 • 202 回帖 • 30 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    4 引用 • 7 回帖
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    19 引用 • 23 回帖 • 741 关注
  • uTools

    uTools 是一个极简、插件化、跨平台的现代桌面软件。通过自由选配丰富的插件,打造你得心应手的工具集合。

    7 引用 • 28 回帖
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 178 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖
  • SVN

    SVN 是 Subversion 的简称,是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统,它的设计目标就是取代 CVS。

    29 引用 • 98 回帖 • 698 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 446 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖 • 1 关注
  • 强迫症

    强迫症(OCD)属于焦虑障碍的一种类型,是一组以强迫思维和强迫行为为主要临床表现的神经精神疾病,其特点为有意识的强迫和反强迫并存,一些毫无意义、甚至违背自己意愿的想法或冲动反反复复侵入患者的日常生活。

    15 引用 • 161 回帖
  • Kafka

    Kafka 是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者规模的网站中的所有动作流数据。 这种动作(网页浏览,搜索和其他用户的行动)是现代系统中许多功能的基础。 这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。

    36 引用 • 35 回帖 • 3 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    6 引用 • 143 回帖
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 672 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 617 关注