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

P45*_*ent 4 c++ java-native-interface

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

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

我需要打电话吗

env->DeleteLocalRef(clz);
Run Code Online (Sandbox Code Playgroud)

一旦我完成了它?我不会回到clzJava,所以我想我需要删除本地引用?这似乎有点奇怪,因为像 a 一样MethodID, ajclass不包含对象实例。

Tho*_*erl 6

调用永远不会错DeleteLocalRef,所以你应该总是调用它,否则你可能会遇到本地引用数量用完的情况。

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

引用官方 Java 文档


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

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


mka*_*aes 3

不,您不需要打电话DeleteLocalRef
FindClass返回本地引用。所以没有必要删除。JNI 调用完成后,JVM 将自动执行此操作。
但如果您愿意,可以删除本地引用。应该没有什么区别。

  • 可用的本地参考数量有限(但可配置)。因此,如果引用是在循环中创建的,最佳实践是删除。[参考](http://www.soi.city.ac.uk/~kloukin/IN2P3/material/jni.pdf) (8认同)