JNI函数学习整理

本文适合初学JNI的同学,刚开始用JNI写代码很多函数记不住,一段时间不用又忘记了,所以抽时间整理了这篇文章,便于大家学习和记忆。参考文献里有整理后的Xmind和TestCode,便于大家练习代码。

这篇文章是基于参考资料[1]中第十三章"JNI Functions"整理的,总的来看,JNI的接口可以整理为如下几类:

JNI函数学习整理

JNI函数学习整理

 

JNI函数学习整理

[0 整理思路]

由参考资料[1]中第十三章"JNI Functions"中,我们可以将jni functions大致分为如下四大类:

1 由VM直接导出的调用接口函数

2 JavaVM接口

3 Native库中定义的函数

4 JNIEnv接口

我们将按照如上顺序,学习jni functions.

 

[1 由VM直接导出的调用接口函数]

JNI中操作JVM的声明:

1 JNI_GetDefaultJavaVMInitArgs

返回Java虚拟机实现的默认配置。

2 JNI_CreateJavaVM

加载并初始化一个虚拟机实例。

3 JNI_GetCreatedJavaVMs

返回指针,指向创建过的所有虚拟机实例。

注意:这三个接口只是由VM为JNI导出的三个符号!!!一般不用用户调用!!!

 

[2 JavaVM接口]

1 DestroyJavaVM                  

卸载一个虚拟机实例并释放它的资源。

2 AttachCurrentThread

绑定当前线程到一个虚拟机实例。

3 DetachCurrentThread

使得当前线程脱离一个虚拟机实例。

4 GetEnv

第一,用来检查当前线程是否绑定到给定的虚拟机实例,env设置为NULL,返回错误JNI_EDETACHED.

其次,可以用来获取其他接口,如JNIEnv interface.

 

[3 Native库中定义的函数]

1 JNI_OnLoad

当虚拟机加载一个native库时,调用JNI_OnLoad接口。

即System.loadLibrary会触发调用JNI_OnLoad接口。

2 JNI_OnUnload

当虚拟机卸载一个native库时,调用JNI_OnUnload接口。

 

[4 JNIEnv接口]

(1)Version Information

1 GetVersion

返回JNIEnv interface的版本号

(2)Class and Interface Operations

1 DefineClass                        

从一个buffer(native byte array)里定义一个类

2 FindClass

返回一个类的引用

3 GetSuperclass

返回基类,除了java.lang.Object类(因为java.lang.Object是最基类)

(3)Exceptions

1 FatalError                         

打印信息并终止当前虚拟机实例

2 ExceptionCheck

检查当前线程是否发生了异常,若有异常返回JNI_TRUE,否则返回JNI_FALSE

3 ExceptionDescribe

JNI层打印异常的堆栈信息!!!

4 ExceptionClear

清除异常堆栈信息

5 Throw and ThrowNew

Throw:丢弃一个现有的异常对象,在当前线程触发一个新的异常

ThrowNew:在当前线程触发一个异常,并自定义输出异常信息

6 ExceptionOccurred

检查当前线程是否发生了异常,若有异常返回该异常的引用,否则返回NULL

(4)Global and Local References

1 NewGlobalRef,DeleteGlobalRef

(1)创建:

调用NewGlobalRef,基于局部引用创建

(2)会阻止GC回收所引用的对象:

意思是只有释放全局引用后GC才可以回收

(3)能跨函数使用,能跨线程使用:

(4)释放:

(i)自动释放:无自动释放

(ii)手动释放:(*env)->DeleteGlobalRef(env,g_cls_string)

2 NewWeakGlobalRef,DeleteWeakGlobalRef

(1)创建:

调用NewWeakGlobalRef,基于局部引用或全局引用创建

(2)不会阻止GC回收所引用的对象:

意思是在GC认为应该回收它的时候(比如内存紧张的时候)会进行自动回收,从而释放全局弱引用

(3)能跨函数使用,能跨线程使用:

(4)释放:

(i)自动释放:在GC认为应该回收它的时候(比如内存紧张的时候)会进行自动回收,释放全局弱引用

(ii)手动释放:(*env)->DeleteWeakGlobalRef(env,g_cls_string)

3 NewLocalRef,DeleteLocalRef

(1)创建:

调用NewLocalRef或其他JNI接口(FindClass、NewObject、NewCharArray)创建。

(2)会阻止GC回收所引用的对象:

意思是只有释放局部引用后GC才可以回收

(3)不能跨函数使用,不能跨线程使用:

(4)释放:

(i)自动释放:函数返回后局部引用的当前所引用的对象会被JVM自动释放

(注意是当前!!!所以局部引用是有内存溢出的风险的!!!

目前理解:只有在函数体内有循环,循环里New局部引用才会出现内存溢出!!!)

(ii)手动释放:(*env)->DeleteLocalRef(env,local_ref)

(5)Object Operations

1 GetObjectClass

返回一个对象对应的类

2 IsInstanceOf

检查一个对象是否是一个类的实例

3 NewObject / NewObjectA / NewObjectV

分配对象空间并构造该对象

4 AllocObject

分配一个未初始化的对象

(6)Instance Field Access

1 GetFieldID

返回实例的域ID

2 Get<Type>Field,Set<Type>Field

获取/设置实例域ID

(7)Static Field Access

1 GetStaticFieldID

返回类的静态域ID

2 GetStatic<Type>Field,SetStatic<Type>Field

获取/设置类静态域ID

(8)Instance Method Calls

1 GetMethodID

返回一个实例方法的方法ID

2 Call<Type>Method / Call<Type>MethodA / Call<Type>MethodV

调用实例方法

3 CallNonvirtual<Type>Method / CallNonvirtual<Type>MethodA / CallNonvirtual<Type>MethodV

调用基类的实例方法

(9)Static Method Calls

1 GetStaticMethodID

返回一个静态方法的方法ID

2 CallStatic<Type>Method

调用静态方法

(10)String Operations

1 NewString

创建一个String对象,表示Unicode字符串

2 NewStringUTF

创建一个String对象,表示UTF-8字符串

3 GetStringLength

返回Unicode字符串的长度

4 GetStringLengthUTF

返回UTF-8字符串的长度

5 GetStringChars/ReleaseStringChars

获取/释放Unicode字符串的指针

6 GetStringUTFChars/ReleaseStringUTFChars

获取/释放UTF-8字符串的指针

7 GetStringCritical/ReleaseStringCritical

获取/释放String对象

8 GetStringRegion/GetStringUTFRegion

拷贝String对象到一个native buffer

(11)Array Operations

1 GetArrayLength

返回数组元素个数

2 NewObjectArray

创建对象数组

3 New<Type>Array

创建基本类型数组(int,char...)

4 GetObjectArrayElement/SetObjectArrayElement

获取/设置对象数组元素的引用

5 Get<Type>ArrayElements/Release<Type>ArrayElements

获取/释放基本类型数组的全部元素

6 Get<Type>ArrayRegion/Set<Type>ArrayRegion

拷贝基本类型数组的元素

7 GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical

获取/释放基本类型数组元素

(12)Native Method Registration

1 RegisterNatives/UnregisterNatives

注册/注销native方法

(13)Monitor Operations

1  MonitorEnter

2  MonitorExit

同步用

(14)JavaVM Interface

1  GetJavaVM

返回当前虚拟机实例的JavaVM指针

(15)Reflection Support

1  FromReflectedField

将java.lang.reflect.Field实例转化为域ID

2  FromReflectedMethod

将java.lang.reflect.Method|java.lang.reflect.Constructor实例转化为方法ID

3  ToReflectedField/ToReflectedMethod

同以上相反方向转换

 

[5 参考资料]

[1]The Java™ Native Interface Programmer’s Guide and Specification.pdf

[2]JNI/NDK开发指南

https://blog.****.net/xyang81/article/category/2759987

[3]Xmind和TestCode见链接

链接:https://pan.baidu.com/s/10ICfMzHlfrVjlCC05Gf8tA

提取码:kl6a