我理解当从Java到C进行调用时,不需要释放GetDirectBufferAddress
方法获得的内存。垃圾收集器知道何时回收内存。在我的例子中,我从C调用Java方法。这是我的Java方法的代码片段:
ByteBuffer processTask() {
...
ByteBuffer retVal = ByteBuffer.allocateDirect(len);
return retVal;
}
以下是我的C函数的代码片段:
jobject retVal = invokeProcessTask();
uint8_t* buf = (uint8_t*) env->GetDirectBufferAddress(retVal);
在这种情况下,我认为垃圾收集器不知道何时收集ByteBuffer
实例。我想我的C代码有责任释放这个记忆。这是正确的吗?如果是这样,我需要调用哪个函数来释放它?问候。
答案 0 :(得分:1)
JNI文档似乎没有说清楚。他们确实说JNI函数返回的所有Java对象都是本地引用,我认为无论是否在更广泛的本机方法调用范围内调用JNI函数,我都没有理由这样做。 VM负责跟踪传递给本机代码的对象,以便在使用时不对GC进行跟踪,我认为有必要解释"传递"包括"返回"。
因此,我倾向于同意这样的解释:当Java VM嵌入在C程序中时,程序通过调用Java范围之外的JNI函数来获得对Java对象的引用 - > C本机方法调用,在C程序明确释放其引用(至少)之前,引用的对象及其可从中访问的所有对象仍然不适用于GC。该程序可以通过DeleteLocalRef()
函数发布本地引用。
另请注意,JNI在任何给定时间仅提供有限数量的本地引用以在同一JNI环境中生存。该数字可以通过EnsureLocalCapacity()
,PushLocalFrame()
和PopLocalFrame()
来管理,但您必须注意避免超过它,这可能比您描述的嵌入方案更具风险是一个短期运行的,窄范围的本机方法调用。
答案 1 :(得分:0)
你可以调用DeleteLocalRef()
,但除非C方法真的长时间运行,否则可能没有必要:GC可以在JNI方法返回后的任何时候收集它。