IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> JVM 虚拟机系列:架构(二)一图看懂虚拟机架构:JNI -> 正文阅读

[移动开发]JVM 虚拟机系列:架构(二)一图看懂虚拟机架构:JNI

1:前言

在 Android 生态中主要有 C/C++、Java、Kotlin 三种语言 ,它们的关系不是替换而是互补。其中,C/C++ 的语境是算法和高性能,Java 的语境是平台无关和内存管理,而 Kotlin 则融合了多种语言中的优秀特性,带来了一种更现代化的编程方式;

JNI 是实现 Java 代码与 C/C++ 代码交互的特性, 思考一个问题 —— Java 虚拟机是如何实现两种毫不相干的语言的交互的呢?今天,我们来全面总结 JNI 开发知识框架。

1.1 为什么要使用 JNI?

JNI(Java Native Interface,Java 本地接口)是 Java 生态的特性,它扩展了 Java 虚拟机的能力,使得 Java 代码可以与 C/C++ 代码进行交互。通过 JNI 接口,Java 代码可以调用 C/C++ 代码,C/C++ 代码也可以调用 Java 代码。

这就引出第 1 个问题(为什么要这么做):Java 为什么要调用 C/C++ 代码,而不是直接用 Java 开发需求呢?我认为主要有 4 个原因:

??原因 1?- Java 天然需要 JNI 技术:虽然 Java 是平台无关性语言,但运行 Java 语言的虚拟机是运行在具体平台上的,所以 Java 虚拟机是平台相关的。因此,对于调用平台 API 的功能(例如打开文件功能,在 Window 平台是 openFile 函数,而在 Linux 平台是 open 函数)时,虽然在 Java 语言层是平台无关的,但背后只能通过 JNI 技术在 Native 层分别调用不同平台 API。类似的,对于有操作硬件需求的程序,也只能通过 C/C++ 实现对硬件的操作,再通过 JNI 调用;

??原因 2?- Java 运行效率不及 C/C++:Java 代码的运行效率相对于 C/C++ 要低一些,因此,对于有密集计算(例如实时渲染、音视频处理、游戏引擎等)需求的程序,会选择用 C/C++ 实现,再通过 JNI 调用;

??原因 3?- Native 层代码安全性更高:反编译 so 文件的难度比反编译 Class 文件高,一些跟密码相关的功能会选择用 C/C++ 实现,再通过 JNI 调用;

??原因 4?- 复用现有代码:当 C/C++ 存在程序需要的功能时,则可以直接复用。

问题2:(为什么可以这么做):为什么两种独立的语言可以实现交互呢?

因为 Java 虚拟机本身就是 C/C++ 实现的,无论是 Java 代码还是 C/C++ 代码,最终都是由这个虚拟机支撑,共同使用一个进程空间。JNI 要做的只是在两种语言之间做桥接。

1.2:JNI开发的基本流程?

一个标准的 JNI 开发流程主要包含以下步骤:

1、创建?HelloWorld.java,并声明 native 方法?sayHi();

2、使用 javac 命令编译源文件,生成?HelloWorld.class?字节码文件;

3、使用 javah 命令导出?HelloWorld.h头文件(头文件中包含了本地方法的函数原型);

4、在源文件?HelloWorld.cpp?中实现函数原型;

5、编译本地代码,生成?Hello-World.so?动态原生库文件;

6、在 Java 代码中调用?System.loadLibrary(...)?加载 so 文件;

7、使用 Java 命令运行 HelloWorld 程序。

?1.3 JNI性能误区

JNI 本身本身并不能解决性能问题,错误地使用 JNI 反而可能引入新的性能问题,这些问题都是要注意的:

??问题 1?- 跨越 JNI 边界的调用:从 Java 调用 Native 或从 Native 调用 Java 的成本很高,使用 JNI 时要限制跨越 JNI 边界的调用次数;

??问题 2?- 引用类型数据的回收:由于引用类型数据(例如字符串、数组)传递到 JNI 层的只是一个指针,为避免该对象被垃圾回收虚拟机会固定住(pin)对象,在 JNI 方法返回前会阻止其垃圾回收。因此,要尽量缩短 JNI 调用的执行时间,它能够缩短对象被固定的时间(关于引用类型数据的处理,在下文会说到)。

1.4 注册JNI函数的方式

Java 的?native?方法和 JNI 函数是一一对应的映射关系,建立这种映射关系的注册方式有 2 种:

??方式 1?- 静态注册:基于命名约定建立映射关系;

??方式 2?- 动态注册:通过?JNINativeMethod?结构体建立映射关系。

关于注册 JNI 函数的更多原理分析,见?注册 JNI 函数

1.5 加载So库的时机

so 库需要在运行时调用?System.loadLibrary(…)?加载,一般有 2 种调用时机:

1、在类静态初始化中:如果只在一个类或者很少类中使用到该 so 库,则最常见的方式是在类的静态初始化块中调用;

2、在 Application 初始化时调用:如果有很多类需要使用到该 so 库,则可以考虑在 Application 初始化等场景中提前加载。

2: JNI模板代码

3:参考文献

JNI 从入门到实践,万字爆肝详解!

?

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:26:57  更:2022-10-22 21:27:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 1:05:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码