Android开发经验谈Android技术知识Android开发

“JNI” 在 Android 开发中的应用你了解多少?

2022-05-31  本文已影响0人  程序老秃子

JNI 简介

JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植;从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互

本地代码与 Java 虚拟机之间是通过 JNI 函数实现相互操作的;JNI 函数通过接口指针来获得,本地方法将 JNI 接口指针当作参数来接受;虚拟机保证在从相同的 Java 线程中对本地方法进行多次调用时,传递给本地方法的接口指针是相同的,本地方法被不同的 Java 线程调用时,它接受不同的 JNI接口指针

使用JNI和算法进行交互,主要是为了提高算法的性能,最大化的利用机器硬件资源

Android 中的语言层

可以将语言层分成Java层和Native层;为什么会有Native层呢?是因为在Java出现之前,很多的功能和系统都是由Native语言写的,所以Java出现之后就不必重复造轮子,直接调用这些方法就行了,而且Native层更接近汇编语言,所以性能更优

所以代码中就出现了Java层调用Native层的方法,而这个跨语言的调用过程就是 JNI

下图就是他们的关系:

当Java语言无法处理一些任务的时候,就可以使用JNI来完成

下面是几个 JNI 的应用场景:

需要调用Java语言不支持的依赖于操作系统平台特性的一些功能

● 需要调用当前UNIX系统的某个功能,而Java不支持这个功能的时候,就要用到JNI

● 在程序对时间敏感或对性能要求特别高时,有必要用到更底层的语言来提高运行效率

● 音视频开发涉及到的音视频编解码需要更快的处理速度,这就需要用到JNI

● 为了整合一些以前的非Java语言开发的系统

● 需要用到早期实现的C/C++语言开发的一些功能或者系统,将这些功能整合到当前的系统或者新的版本中

JNI是完善Java的一个重要功能,它让Java更加全面、封装了各个平台的差异性

JNI在 Android 开发里的应用主要有:

● 音视频开发

● 热修复

● 插件化

● 逆向开发

● 等等…

为了更好的使用JNI,Android提供了NDK这个工具,NDK基于JNI,所以理解了JNI,NDK也会很容易掌握

JNI 中的引用类型

Java中提供了四种引用类型,可以帮助垃圾回收。同样jni也提供了引用类型

● 本地引用(LocalReferences)

● 全局引用(Global References)

● 弱全局引用(Weak GlobalReferences)

本地引用

JNIEnv 提供的函数中定义的非全局的引用基本上都是本地引用,因此本地引用也是JNI中最常见的引用类型

本地引用最大的特点当Native函数返回时,这个本地引用就会被自动释放;所以此引用是JVM负责的引用类型,受JVM管理

我们也可以使用JNIEnv的DeleteLocalRef函数来手动删除本地引用

全局引用

在native函数返回时不会被自动释放,因此全局引用需要手动来进行释放,并且不会被GC回收

JNIEnv的NewGlobalRef函数用来创建全局引用,调用JNIEnv的DeleteGlobalRef函数来释放全局引用

全局引用不受到JVM管理

弱全局引用

是一种特殊的全局引用;它和全局引用的特点相似,不同的是弱全局是可以被GC回收的,弱全局引用被GC回收之后会指向NULL

在运行过程中可能会被垃圾回收;所以使用它之前,需要调用 JNIEnv 的 isSameObject 判断它是否被回收

JNI 的异常处理

JNI 中也有异常,不过它和 C++、Java 的异常不太一样;如果调用 JNIEnv 的某些函数出错了,则会产生一个异常,但这个异常不会中断本地函数的执行,直到从 JNI 层返回到 Java 层后,虚拟机才会抛出这个异常

虽然在 JNI 层中产生的异常不会中断本地函数的运行;但一旦产生异常后,就只能做一些资源清理工作了(例如释放全局引用,或者 ReleaseStringChars);如果这时调用除上面所说函数之外的其他 JNIEnv 函数,则会导致程序死掉

JNI 层函数可以在代码中截获和修改这些异常,JNIEnv 提供了三个函数给予帮助:

● ExceptionOccured 函数,用来判断是否发生异常

● ExceptionClear 函数,用来清理当前 JNI 层中发生的异常

● ThrowNew 函数,用来向 Java 层抛出异常

JNI 特点:

二进制兼容

● 本地方法库与同一平台上所有Java 虚拟机之间实现二进制兼容,即对于给定平台开发人员只需要维护一种版本的本地方法库

效率高

为了实现实时系统,JNI 在效率与虚拟机无关性之间进行了优化,以保障高效运行

功能强

● JNI 提供了大量的函数及接口让本地方法与Java 虚拟机内核相互操作,增强两者的功能

本地代码与 Java 虚拟机之间是通过 JNI 函数实现相互操作的;JNI 函数通过接口指针来获得,本地方法将 JNI 接口指针当作参数来接受;虚拟机保证在从相同的 Java 线程中对本地方法进行多次调用时,传递给本地方法的接口指针是相同的,本地方法被不同的 Java 线程调用时,它接受不同的 JNI接口指针

尾述

点击 此处 即可 免费获取 更多学习笔记 面试视频

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,与君共勉

PS:有问题欢迎指正,可以在评论区留下你的建议和感受;
欢迎大家点赞评论,觉得内容可以的话,可以转发分享一下

上一篇下一篇

猜你喜欢

热点阅读