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

时间:2019-07-08 09:17:55

标签: java-native-interface

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

jstring jStr = (jstring)env->CallStaticObjectMethod(myApplicationClass, getString);

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

2 个答案:

答案 0 :(得分:3)

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

您可能想在其中使用DeleteLocalRef的{​​{3}}:

  

本机方法访问大型Java对象,从而创建对该Java对象的本地引用。然后,本机方法执行   返回调用者之前进行其他计算。本地的   引用大型Java对象将防止该对象被   垃圾收集,即使该对象不再用于   计算的其余部分。

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

请注意,这种情况是关于JNI函数的,该函数从Java称为。 通过将本机线程附加到JVM,您可能会遇到相反的情况,即您的本机代码将传入到JVM。在这种情况下,JVM将自动释放您的本地引用,而您需要自己删除本地引用。

作为这种情况的一个具体示例,在JNI specification outlines two cases中创建的所有本地引用都将持续存在;他们永远不会手动清理。

  

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

这很简单:本地引用的数量有上限。

答案 1 :(得分:1)

是的,您必须处理Java回调返回的本地引用。适用标准规则:您可以使用PushLocalFrame()/ PopLocalFrame()代替DeleteLocalRef(),或者当线程与JVM分离时,本地引用将自动释放,或者本机方法返回Java(如果发生在内部,一种本地方法)。