假设我在实现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调用完成后自动执行此操作。
但是如果你愿意,你可以删除本地引用。