使用JNIEnv::FindClass:我需要释放返回的jclass引用

Using JNIEnv::FindClass: do I need to free the returned jclass reference?

本文关键字:返回 jclass 释放 引用 JNIEnv FindClass 使用      更新时间:2023-10-16

假设我在实现native函数存根的JNI函数中有以下代码:

JNIEnv* env; /*This is set to a valid JNIEnv* for this thread*/
jclass clz = env->FindClass("foo"); /*this has worked*/

我需要打电话吗

env->DeleteLocalRef(clz);

一旦我完成它?我不返回clz回Java,所以我认为我需要删除本地引用?这看起来有点奇怪,因为像MethodID一样,jclass不包含对象实例。

调用DeleteLocalRef永远不会出错,所以您应该始终调用它,否则您可能会遇到本地引用数量用尽的情况。

当你的JNI代码从Java调用时,它是短时间运行的,你可能足够幸运,本地引用在你返回Java调用者后为你清理,但是如果你从本机代码调用Java VM(所以没有"外部"Java VM框架,你的JNI代码被调用),那么你将很快用完你的本地变量,因为它们永远不会被一个不存在的Java调用者删除。

引用Java官方文档:


在大多数情况下,程序员应该依赖VM在本机方法返回后释放所有本地引用。但是,有时程序员应该显式释放局部引用。例如,考虑以下情况:

    本地方法访问一个大的Java对象,从而创建一个对Java对象的本地引用。然后,本机方法在返回调用方之前执行额外的计算。对大Java对象的本地引用将防止该对象被垃圾收集,即使该对象在剩余的计算中不再使用。
  • 本机方法创建了大量的本地引用,尽管不是所有的引用都同时使用。由于VM需要一定的空间来跟踪本地引用,因此创建太多的本地引用可能会导致系统耗尽内存。例如,本机方法循环遍历大型对象数组,检索元素作为局部引用,并在每次迭代时操作一个元素。在每次迭代之后,程序员不再需要对数组元素的局部引用。

不,你不需要调用DeleteLocalRef
FindClass返回一个本地引用。所以没有必要删除。JVM将在JNI调用完成后自动执行此操作。
但是如果你愿意,你可以删除本地引用。