JNI函数学习整理
本文适合初学JNI的同学,刚开始用JNI写代码很多函数记不住,一段时间不用又忘记了,所以抽时间整理了这篇文章,便于大家学习和记忆。参考文献里有整理后的Xmind和TestCode,便于大家练习代码。
这篇文章是基于参考资料[1]中第十三章"JNI Functions"整理的,总的来看,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