我有以下JNI方法,它本地创建一个Java对象集合,然后将它们返回给Java:
JNIEXPORT jobject JNICALL Java_com_test_myClass_myMethod(JNIEnv * env, jclass klass) {
jclass arrayClass = env->FindClass("java/util/ArrayList");
jmethodID initMethod = env->GetMethodID(arrayClass, "<init>", "()V");
jmethodID addMethod = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z");
jobject myArray = env->NewObject(arrayClass, initMethod);
env->CallBooleanMethod(myArray, addMethod, env->NewStringUTF("Hello"));
env->CallBooleanMethod(myArray, addMethod, env->NewStringUTF("World"));
return myArray;
}
我是否需要释放在本机代码中创建的对象,还是由GC自动完成? 如果我这样做,我该怎么做,因为我需要将它返回给Java?
答案 0 :(得分:13)
您不需要释放在本机代码中创建的Java对象。事实上,你不能。当没有进一步的引用时,垃圾收集器可以释放该对象。
有时,在本机代码中将引用释放到Java对象是很有用的。这可以减少本机代码保存但不再需要对大对象或大量引用的引用时的内存要求。
来自:JNI specification中的“全局和本地参考”。
在大多数情况下,程序员应该依赖VM在本机方法返回后释放所有本地引用。但是,有时程序员应该明确地释放本地引用。例如,考虑以下情况:
- 本机方法访问大型Java对象,从而创建对Java对象的本地引用。然后,本机方法在返回调用方之前执行其他计算。对大型Java对象的本地引用将阻止对象被垃圾回收,即使该对象不再用于计算的其余部分。
- 本机方法会创建大量本地引用,但并非所有引用都同时使用。由于VM需要一定的空间来跟踪本地引用,因此创建太多本地引用可能会导致系统内存不足。例如,本机方法循环遍历大量对象,将元素作为本地引用检索,并在每次迭代时对一个元素进行操作。在每次迭代之后,程序员不再需要对数组元素的本地引用。
提供了更多细节 请参阅JNI程序员指南中的"Freeing References"。