我是否需要删除 JNI 调用返回的 jstring 对象?

Vio*_*ffe 5 java-native-interface

假设我使用 JNI 调用一些返回 的 Java 方法String,即jstring在本机代码中:

jstring jStr = (jstring)env->CallStaticObjectMethod(myApplicationClass, getString);
Run Code Online (Sandbox Code Playgroud)

那我需要打电话吗env->DeleteLocalRef(jStr)?我想我是这样做的,但是我在 JNI 参考中找不到任何具体的说明,而且我可以看到我有很多代码没有调用它 - 经过尝试的真实代码。但是,如果存在轻微的内存泄漏,没有人会注意到,因为此代码不会创建很多对象。

Bot*_*tje 6

当 JNI 调用的函数返回到 Java 时,您创建的每个本地引用都会自动释放。

JNI规范概述了您可能想要使用的两种情况DeleteLocalRef

本机方法访问大型 Java 对象,从而创建对该 Java 对象的本地引用。然后,本机方法在返回调用者之前执行额外的计算。对大型 Java 对象的本地引用将阻止该对象被垃圾回收,即使该对象在剩余的计算中不再使用。

换句话说,如果您分配了一个多兆字节的字符串并且不再需要它,您可以立即删除该引用,而不是在返回时将其留给 JVM。但是,只有当您需要在返回之前在 JNI 世界中执行其他步骤时,这才有用。

请注意,这种情况讨论的是从 Java调用的 JNI 函数。通过将本机线程附加到 JVM,您最终可能会遇到相反的情况,即本机代码调用JVM。在这种情况下,JVM 不会自动释放您的本地引用,您需要自己删除本地引用。

作为这种情况的一个具体示例, JNI 说明书中此函数中创建的所有本地引用都将保留;它们永远不会被手动清理。

本机方法创建大量本地引用,尽管并非所有本地引用都会同时使用。由于虚拟机需要一定的空间来跟踪本地引用,因此创建过多的本地引用可能会导致系统内存不足。例如,本机方法循环遍历一大堆对象,检索元素作为本地引用,并在每次迭代时对一个元素进行操作。每次迭代之后,程序员不再需要对数组元素的本地引用。

这个比较简单:本地引用的数量有一个上限。