JNI 函数(二)全局及局部引用
(一)、创建全局引用
函数原型:jobject NewGlobalRef(JNIEnv *env, object obj);
给对象 obj 创建一个全局引用,obj 可以是全局或局部引用。全局引用必须通过 DeleteGlobalRef() 显示处理。
参数:
env:JNI 接口指针
obj:object 对象
返回:
全局引用 jobject,如果内存溢出则返回 NULL
(二)、删除全局引用
函数原型:void DeleteGlobalRef(JNIEnv *env, jobject globalRef);
删除全局引用
参数:
env:JNI 接口指针
globalRef:需要被删除的全局引用
(三)、删除局部引用
局部引用只在本地接口调用时的生命周期内有效,当本地方法返回时,它们会被自动释放。每个局部引用都会消耗一定的虚拟机资源,虽然局部引用可以被自动销毁,但是程序员也需要注意不要在本地方法中过度分配局部引用,过度分配局部引用会导致虚拟机在执行本地方法时内存溢出。
函数原型:void DeleteLocalRef(JNIEnv *env, jobject localRef);
通过 localRef 删除局部引用
参数:
env:JNI 接口指针
localRef:需要被删除的局部引用
JDK/JRE 1.1 提供了上面的 DeleteLocalRef 函数,这样程序员就可以手动删除本地引用。
从JDK/JRE 1.2 开始,提供可一组生命周期管理的函数,他们是下面四个函数。
(四)、设定局部变量的容量
函数原型:jint EnsureLocalCapacity(JNIEnv *env, jint capacity);
在当前线程中,通过传入一个容量 capacity,,限制局部引用创建的数量。成功则返回 0,否则返回一个负数,并抛出一个 OutOfMemoryError。VM 会自动确保至少可以创建 16 个局部引用。
参数:
env:JNI 接口指针
capacity:容量
返回:
成功返回 0,失败返回一个负数,并会抛出一个 OutOfMemoryError
为了向后兼容,如果虚拟机创建了超出容量的局部引用。VM 调用 FatalError,来保证不能创建更多的本地引用。(如果是 debug 模式,虚拟机回想用户发出 warning,并提示创建了更多的局部引用,在 JDK 中,程序员可以提供 -verbose:jni 命令行选项来打开这个消息)
(五)、在老的上创建一个新的帧
函数原型:jint PushLocalFram(JNIEnv *env , jint capacity);
在已经设置设置了局部变量容量的情况下, 重新创建一个局部变量容器。成功返回0,失败返回一个负数并抛出一个OutOfMemoryError异常。
注意:当前的局部帧中,前面的局部帧创建的局部引用仍然是有效的
参数:
env:JNI 接口指针
capacity:容量
(六)、释放一个局部引用
函数原型:jobject PopLocalFrame(JNIEnv *env, jobject result)
弹出当前的局部引用帧,并且释放所有的局部引用。返回在之前局部引用帧与给定result对象对应的局部引用。如果不需要返回任何引用,则设置 result 为 NULL
参数:
env:JNI 接口指针
result:需要释放的局部引用
(七)、创建一个局部引用
函数原型:jobject NewLocalRef(JNIEnv *env, jobject ref);
创建一个引用自 ref 的局部引用。ref 可以是全局或者局部引用,如果 ref 为 NULL,则返回 NULL。
参数:
env:JNI 接口指针
ref:可以试试局部引用也可以是全局引用。
(八)、弱全局引用
弱全局引用是一种特殊的全局引用,不像一般的全局引用,一个弱全局引用允许底层 Java 对象能够被垃圾回收。弱全局引用能够应用在任何全局或局部引用被使用的地方。当垃圾回收器运行的时候,如果对象只被弱引用所引用时,它将释放底层变量。一个弱引用指向一个被释放的对象相当于等于 NULL。编程人员可以通过使用 isSampleObject 对比弱引用和 NULL 来检测一个弱全局应用是否指向一个被释放的对象。弱全局引用在 JNI 中是 Java 弱引用的一个简化版本,在 Java 平台 API 中有有效。
当 Native 方法正在运行的时候,垃圾回收器可能正在工作,被弱引用所指向的对象可能在任何时候被释放。弱全局引用能够应用在任何全局引用所使用的地方,通常是不太适合那么做的,因为它们可能在不注意的时候编程 NULL。
当 IsSampleObject 能够识别一个弱全局引用是不是指向一个被释放的对象,但是这不妨碍这个对象在被检测之后马上被释放。这就说明了,程序员不能依赖这个方法来识别一个弱全局引用是否能够在后续的 JNI 函数调用中被使用。
如果想解决上述的问题,建议使用 JNI 函数 NewLocalRef 或者 NewGlobalRef 来用标准的全局也引用或者局部引用来指向相同的对象。如果这个独享已经被释放了这些函数会返回 NULL。否则会返回一个强引用(这样就可以保证这个对象不会被释放)。当不需要访问这个对象时,新的引用必须显式被删除。
1、创建全局弱引用
函数原型:jweak NewWeakGlobalRef(JNIEnv *env,jobject obj);
创建一个新的弱全局引用。如果 obj 指向 NULL,则返回 NULL。如果 VM 内存溢出,将会抛出异常 OutOfMemoryError。
参数:
env:JNI 接口指针
obj:引用对象
返回:
全局弱引用
2、删除全局弱引用
函数原型:void DeleteWeakGlobalRef(JNIEnv *env,jweak obj);
VM 根据所给定的弱全局引用删除对应的资源。
参数:
env:JNI 接口指针
obj:将删除的弱全局引