1 JNI定义
JNI(Java Native Interface),即Java本地接口,JNI是Java调用Native 语言的一种特性。通过JNI可以使得Java与C/C++机型交互.
以下是oracle对JNI的定义
JavaTM Native Interface (JNI) is a standard programming interface for writing Java native methods and embedding the JavaTM virtual machine* into native applications. The primary goal is binary compatibility of native method libraries across all Java virtual machine implementations on a given platform.
更多oracle关于JNI的介绍可以参考 Java 原生接口规范
2 JNI介绍
Java语言的执行环境是Java虚拟机(JVM),JVM其实是主机环境中的一个进程,每个JVM虚拟机都在本地环境中有一个JavaVM结构体,该结构体在创建Java虚拟机时被返回,在JNI环境中创建JVM的函数为JNI_CreateJavaVM。
Native code通过JNI Function来访问Java VM的功能. JNI Function可以通过接口指针JNIEnv*来访问, 该指针指向一个指针数组,每个指针指向一个接口函数。 每个接口函数都在数组内的预定义偏移处。下图说明了接口指针的组织。
3 JavaVM 和 JNIEnv
JNI 定义了两个关键数据结构,即“JavaVM”和“JNIEnv”。两者本质上都是指向函数表的二级指针。
JavaVM
理论上,每个进程可以有多个 JavaVM,但 Android 只允许有一个。JavaVM中封装的这些函数指针主要是对JVM操作接口.比较常用的是使用 AttachCurrentThread()来获取JNIEnv结构体.
JavaVM的获取方式:
第一种方式,在加载动态链接库的时候,JVM会调用JNI_OnLoad(JavaVM* jvm, void* reserved)(如果定义了该函数)。第一个参数会传入JavaVM指针。
第二种方式,在native code中调用JNI_CreateJavaVM(&jvm, (void*)&env, &vm_args)可以得到JavaVM指针。
可以用全局变量,比如JavaVM g_jvm来保存获得的指针以便在任意上下文中使用。
在C和C++中的JavaVM的定义有所不同,在C中JavaVM是JNIInvokeInterface_类型指针,而在C++中有对JNIInvokeInterface_进行了一次封装JNIEnv
JNIEnv提供了大部分 JNI 函数。原生函数第一个参数就是JNIEnv 。JNIEnv是当前Java线程的执行环境,因此,无法在线程之间共享 JNIEnv。如果一段代码无法通过其他方法获取自己的 JNIEnv,应该共享相应 JavaVM,然后使用 GetEnv 发现线程的 JNIEnv(关于线程在下一篇文章里面介绍)。开发者可以通过JNIEnv调用Java函数和操作Java代码
4 jobject与jclass类型
jobject与jclass通常作为JNI函数的第二个参数,当所声明Native方法是静态方法时,对应参数类型jclass,因为静态方法不依赖对象实例,而依赖于类,所以参数中传递的是一个jclass类型。如果声明的Native方法时非静态方法时,那么对应参数是jobject。
5 JNI数据类型
基本数据类型
Java类型 | JNI类型 | 描述 |
---|---|---|
boolean | jboolean | unsigned 8 bits |
byte | jbyte | signed 8 bits |
char | jchar | unsigned 16 bits |
short | jshort | signed 16 bits |
int | jint | signed 32 bits |
long | jlong | signed 64 bits |
float | jfloat | 32 bits |
double | jdouble | 64 bits |
void | void | N/A |
引用数据类型
Java类型 | JNI类型 | 描述 |
---|---|---|
Object | jobject | 任何Java对象 |
class | jclass | class对象 |
String | jstring | 字符串对象 |
Object[] | jobjectArray | 对象数组 |
boolean[] | jbooleanArray | 布尔类型数组 |
char[] | jbyteArray | 字符数组 |
int[] | jintArray | int数组 |
long[] | jlongArray | long数组 |
float[] | jfloatArray | float数组 |
double[] | jdoubleArray | double数组 |
Throwable | jthrowable |
参考
https://www.jianshu.com/p/87ce6f565d37
https://developer.android.google.cn/training/articles/perf-jni