JNI:java native方法与JNI实现
JNI
JNI & NDK
JNI & NDK 定义 & 介绍 & 区别
JNI | NDK | |
定义 | Java Native Interface,即 Java本地接口 | Native Development Kit,是 Android的一个工具开发包 |
简介 | 使得Java 与 本地其他类型语言(如C、C++)交互 即在 Java代码 里调用 C、C++等语言的代码 或 C、C++代码调用 Java 代码 | 快速开发C、 C++的动态库,并自动将so和应用一起打包成 APK 即可通过NDK在Android中使用JNI与本地代码(C/C++)交互 |
作用 | 因为Java具备跨平台的特点,所以Java与本地代码交互能力很弱,通过 JNI 增强Java与本地代码进行交互能力 1. 运行效率高:java是解释型语言,运行效率较低,C/C++效率高很多通过JNI把耗时操作交给C/C++能提高Java运行效率 2. 安全性高:java代码编译成的.class文件安全性较低,可通过JNI把重要的业务逻辑交给C/C++实现。由于C/C++反编译困难,因此安全性较高 3. 功能扩展性好:可以方便使用其他开发语言的开源哭 4. 易于代码复用和移植:使用本地代码(C/C++)开发的代码不仅可以在Android使用,还可以在别的平台上使用 | |
使用 | 1. 在Java中声明Native方法(即需要调用的本地方法) 2. 编译上述 Java源文件javac(得到 .class文件) 3. 通过 javah 命令导出JNI的头文件(.h文件) 4. 使用 Java需要交互的本地代码 实现在 Java中声明的Native方法 5. 编译.so库文件 6. 通过Java命令执行 Java程序,最终实现Java调用本地代码 | 1. 配置 Android NDK环境 2. 创建 Android 项目,并与 NDK进行关联 3. 在 Android 项目中声明所需要调用的 Native方法 4. 使用 Android需要交互的本地代码 实现在Android中声明的Native方法(比如 Android 需要与 C++ 交互,那么就用C++ 实现 Java的Native方法) 5. 通过 ndk - bulid 命令编译产生.so库文件 6. 编译 Android Studio 工程,从而实现 Android 调用本地代码 |
联系 | JNI是实现的目的,NDK是Android中实现JNI的工具。 在Android开发环境中,通过 NDK开发工具包 实现 JNI 的功能(实现java 与本地语言交互) |
JNI 原理 —— 为什么java能够调用c/c++函数
(1)创建JNI函数并最终编译成.dll(Windows)/.so(Unix)(这里文件类型根据机器类型自动生成)
- 编写带有native声明的方法的java类,生成.java文件
- 使用javac命令编译所编写的java类,生成.class文件
- 使用javah -jni java类名生成扩展名为h的头文件,也即生成.h文件
- 使用C/C++(或者其他编程想语言)实现本地方法,创建.h文件的实现,也就是创建.cpp文件实现.h文件中的方法
- 将C/C++编写的文件生成动态连接库,生成dll文件
(2)当一个类第一次被使用到时,这个类的字节码会被加载到内存,并且只会加载一次。在这个被加载的字节码的入口维持着一个该类所有方法描述符的list,这些方法描述符包含这样一些信息:方法代码存于何处,它有哪些参数,方法的描述符(public之类)等等。
如果一个方法描述符内有native,这个描述符块将有一个指向该方法的实现的指针。这些实现在一些DLL文件内,但是它们会被操作系统加载到java程序的地址空间。当本地方法被调用时,虚拟机通过调用java.system.loadLibrary()加载这些DLL文件实现本地方法。
JNI如何实现数据传递?
- Java调用C/C++语言
在Java中声明Native方法(即需要调用的本地方法)
编译上述 Java源文件javac(得到 .class文件)
通过 javah 命令导出JNI的头文件(.h文件)
使用 Java需要交互的本地代码 实现在 Java中声明的Native方法
编译.so库文件
通过Java命令执行 Java程序,最终实现Java调用本地代码 - JNI调用Java层代码
从classpath路径下搜索ClassMethod这个类,并返回该类的Class对象
获取类的默认构造方法ID
查找实例方法的ID
创建该类的实例
调用对象的实例方法