【面向面试学习】JNI如何实现数据传递?

2,107 阅读2分钟

传递基本数据类型

Java类型 JNI类型 描述
boolean Jboolean 无符号8位
byte Jbyte 无符号8位
char Jchar 无符号16位
short Jshort 有符号16位
int Jint 有符号32位
long Jlong 有符号64位
float Jfloat 有符号32位
double Jdouble 有符号64位

传递Java引用

Java层各种引用类型传递到Native层都转为jobject的结构体指针类型

Java类型 JNI类型
Object jclass
String jstring
Throwable jthrowable
Object Arrays jobjectArray
Boolean Arrays jbooleanArray
Byte Arrays jbyteArray
Char Arrays jcharArray
Short Arrays jshortArray
Int Arrays jintArray
Long Arrays jlongArray
Float Arrays jfloatArray
Double Arrays jdoubleArray

String参数的传递

Java的String和C++的string是不能对等起来的,要专门处理,JNI提供了一些列操作方法

方法 作用
NewString 在Native根据char数组创建一个Java的String对象
GetStringLength 在Native层获取一个Java String的长度
GetStringChars 获取Native层一个指向Java的string的指针
ReleaseStringChars 告诉虚拟机Native层不在需要指向的那个JavaString
NewStringUTF 在Native层创建一个根据Modified UTF-8编码的JavaString
GetStringUTFLength 获取NewStringUTF产生的字符长度
GetStringUTFChars 获取指向NewStringUTF的指针
ReleaseStringUTFChars 不在引用指针指向的String
GetStringRegion 获取String的某一段
GetStringUTFRegion 获取Modified UTF-8编码的String的一段
GetStringCritical 约等于GetStringChars但是Critical会让虚拟机暂停GC
ReleaseStringCritical 约等于ReleaseStringChars,会让虚拟机的GC恢复

通过Direct Buffer传递数据

DirectBuffer这个概念不是JNI独有,是计算机领域一个经典的理论,广泛的存在于各种操作系统,大型软件中,主要思想是,直接在内存中开辟一块内存Buffer,生产者直接把数据放入Buffer,消费者直接从Buffer中取数据去计算,在一些生产者消费者无法直接通信,或者传递数据复杂困难的场景下,是一个绕过很多步骤,简单直接的数据传递方式。

回到JNI来说,就是Java层面通过JNI在内存上开辟一个Buffer,Java领域管这叫堆外内存,也就说不占用虚拟机所管辖的内存,然后Native层直接访问这块Buffer就能拿到数据。

优点:比普通数组传输效率高,双方解耦,非强类型,一个只管放,另一方只管拿来,按自己的需求解析Buffer里的数据 缺点:开辟,回收维护成本高

参考

Android NDK开发(二)JNI传递参数和返回值 JNI之String类型 Java层与Jni层数据传递之Direct Buffer