JNI 基础知识
JNI 基础知识
什么是 JNI ?
JNI (Java Native Interface) 是 Java 沟通 Native 语言(主要是C、C++)的桥梁。
Native 语言有着更高的性能,更重要的是还有庞大的 Native 语言所编写的库。
这些给 Java 语言提供很多性能优秀的强大功能支持。
JNI 能够提供 Java 更快速的 Native 功能移植,也能利用 C++ 的反汇编能力加强代码安全性。
JNI 数据类型与 Java 、C++ 类型对比
Java 使用 JNI 最主要连接的 Native 语言是 C、C++(C++可以兼容C)。
因此这里介绍 Java 类型与 JNI 类型和 C++ 类型的对比关系。
Java 类型 | JNI 类型 | C++ 类型(包含封装的部分) |
---|---|---|
int |
jint / jsize |
long |
long |
jlong |
__int64 |
byte |
jbyte |
signed char |
boolean |
jboolean |
unsigned char |
char |
jchar |
unsigned short |
short |
jshort |
short |
float |
jfloat |
float |
double |
jdouble |
double |
Object |
jobject |
_jobject* |
Java 其它数据类型与 JNI 的关系
Java 还具有其它基础类型,为了方便调用也需要有 JNI 的类型进行对应。
基于常用的类型,有以下关系。
所有的 Class 都继承于 jobject,但是由于层次不一样。
不同的 jobject 的子类型有着不同的获取、调用和释放方式。
JNI 各种对象的方法
方法 | 说明 |
---|---|
FindClass |
加载本地定义的类 |
GetObjectClass |
通过对象获取这个类 |
NewObject |
创建 jobject 类型的对象 |
NewString |
创建 jstring 类型的对象 |
DeleteLocalRef |
删除局部引用 |
DeleteGlobalRef |
删除全局引用 |
New<Type>Array |
创建类型为 Type 的数组对象 |
Get<Type>ArrayElements |
从类型为 Type 的数组对象获取类型为 Type 的数组指针 |
Release<Type>ArrayElements |
根据类型为 Type 的数组对象释放类型为 Type 的数组指针指向的资源 |
Get<Type>Field |
获取类型为 Type 的字段 |
GetStatic<Type>Field |
获取类型为 Type 的 static 字段 |
Set<Type>Field |
设置类型为 Type 的字段 |
SetStatic<Type>Field |
设置类型为 Type 的 static 字段 |
Call<Type>Method |
调用类型为 Type 的方法 |
CallStatic<Type>Method |
调用类型为 Type 的 static 方法 |
还有很多与类有关的方法,利用的频率不高就先不添加了。
JNI 域描述符
Java 类型 | JNI 类型 | 域描述符 | 说明 | 示例 |
---|---|---|---|---|
boolean | jboolean | Z | ||
byte | jbyte | B | ||
char | jchar | C | ||
short | jshort | S | ||
int | jint | I | ||
long | jlong | J | ||
float | jfloat | F | ||
double | jdouble | D | ||
int[] | [I | 一维数组形式,以一个 “[” 表示一维数组 | ||
byte[][] | [[B | N 维数组则以 N 个 “[” 表示 N 维 | ||
String | jstring | Ljava/lang/String; | 类参数,则以 “Lxxx/yyy;” 的形式表示,注意 “L” 开头和 “;” 结尾。xxx/yyy 则是类的路径(都属于 jobject ) | |
返回值 void | V | |||
函数形式 | (xxx)yyy | "()" 内为输入参数,右侧为输出参数 |
JNI 内存泄漏检查
由于 JNI 的机制,凡是创建 jobject 对象(包括其派生),都会在 Heap 申请资源。
及时不使用 jobject 对象,也会有资源占用。
导致退出时需要对 JNI 内的 jobject 对象资源释放。
(如果 jobject 返回到 Java 接口中,由 Java 进行回收)
对于新手的 JNI 开发来说,内存泄漏可能是必然存在的情况。
检查内存泄漏可以使用如下 adb 命令:
adb shell dumpsys meminfo packageName
检查 Native Heap 项,如下图。