1 JNI概念
什么是JNI
JNI 全称 Java Native Interface,Java 本地化接口,可以通过 JNI 调用系统提供的 API。操作系统,无论是 Linux,Windows 还是 Mac OS,或者一些汇编语言写的底层硬件驱动都是 C/C++ 写的。Java和C/C++不同 ,它不会直接编译成平台机器码,而是编译成虚拟机可以运行的Java字节码的.class文件,通过JIT技术即时编译成本地机器码,所以有效率就比不上C/C++代码,JNI技术就解决了这一痛点,JNI 可以说是 C 语言和 Java 语言交流的适配器、中间件。
JNI调用示意图:
什么是NDK?
NDK 全名Native Develop Kit,官方说法:Android NDK 是一套允许您使用 C 和 C++ 等语言,以原生代码实现部分应用的工具集。在开发某些类型的应用时,这有助于您重复使用以这些语言编写的代码库。
JNI与NDK区别
JNI:JNI是一套编程接口,用来实现Java代码与本地的C/C++代码进行交互;
NDK: NDK是Google开发的一套开发和编译工具集,可以生成动态链接库,主要用于Android的JNI开发;
JNI与NDK中都有jni.h文件
jdk中jni.h路径
C:\Program Files\Java\jdk-1.8\include\jni.h路径
ndk中jni.h路径
C:\Users\Administrator\AppData\Local\Android\Sdk\ndk\25.1.8937393\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\include
ndk对jdk的jni.h进行了封装,native c/c++使用的是ndk中的jni.h
JNI在Android中作用
JNI可以调用本地代码库(即C/C++代码),并通过 Dalvik 虚拟机与应用层和应用框架层进行交互,Android中JNI代码主要位于应用层和应用框架层;
- 应用层: 该层是由JNI开发,主要使用标准JNI编程模型;
- 应用框架层: 使用的是Android中自定义的一套JNI编程模型,该自定义的JNI编程模型弥补了标准JNI编程模型的不足;
2 JNI数据类型映射
在 JNI 开发中,Java 的数据类型并不是直接在 JNI 里使用的
2.1 基本数据类型
Java基本数据类型和本地类型的映射关系,这些基本数据类型都是可以直接在 Native 层直接使用的
Java数据类型 | JNI本地类型 | C/C++数据类型 | 数据类型描述 |
boolean | jboolean | unsigned char | C/C++无符号8为整数 |
byte | jbyte | signed char | C/C++有符号8位整数 |
char | jchar | unsigned short | C/C++无符号16位整数 |
short | jshort | signed short | C/C++有符号16位整数 |
int | jint | signed int | C/C++有符号32位整数 |
long | jlong | signed long | C/C++有符号64位整数 |
float | jfloat | float | C/C++32位浮点数 |
double | jdouble | double | C/C++64位浮点数 |
2.2 引用数据类型
引用数据类型和本地类型的映射关系:
Java数据类型 | JNI本地类型 | 数据类型描述 |
java.lang.Object | jobject | 可以表示任何Java的对象,或者没有JNI对应类型的Java对象(实例方法的强制参数) |
java.lang.String | jstring | Java的String字符串类型的对象 |
java.lang.Class | jclass | Java的Class类型对象(静态方法的强制参数) |
Object[] | jobjectArray | Java任何对象的数组表示形式 |
boolean[] | jbooleanArray | Java基本类型boolean的数组表示形式 |
byte[] | jbyteArray | Java基本类型byte的数组表示形式 |
char[] | jcharArray | Java基本类型char的数组表示形式 |
short[] | jshortArray | Java基本类型short的数组表示形式 |
int[] | jintArray | Java基本类型int的数组表示形式 |
long[] | jlongArray | Java基本类型long的数组表示形式 |
float[] | jfloatArray | Java基本类型float的数组表示形式 |
double[] | jdoubleArray | Java基本类型double的数组表示形式 |
java.lang.Throwable | jthrowable | Java的Throwable类型,表示异常的所有类型和子类 |
void | void | N/A |
需要注意的是:
1)引用类型不能直接在 Native 层使用,需要根据 JNI 函数进行类型的转化后,才能使用;
2)多维数组(含二维数组)都是引用类型,需要使用 jobjectArray 类型存取其值;
2.3 方法和变量ID
同样不能直接在 Native 层使用。当 Native 层需要调用 Java 的某个方法时,需要通过 JNI 函数获取它的 ID,根据 ID 调用 JNI 函数获取该方法;变量的获取也是类似。ID 的结构体如下:
struct _jfieldID; /* opaque structure */ typedef struct _jfieldID* jfieldID; /* field IDs */ struct _jmethodID; /* opaque structure */ typedef struct _jmethodID* jmethodID; /* method IDs */```
3 JNI描述符
3.1 域描述符
基本类型描述符
Tips:
除了 boolean 和 long 类型分别是 Z 和 J 外,其他的描述符对应的类型名的大写首字母