JNI 对象创建和内存管理

我有以下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?


答案 1

您不需要释放在本机代码中创建的 Java 对象。事实上,你不能。当没有进一步的引用时,垃圾回收器可能会释放该对象。

有时,在本机代码中,自由引用 Java 对象很有用。当本机代码保留但不再需要对大型对象的引用或大量引用时,这可以降低内存要求。

来自:JNI 规范中的“全局和本地引用”。

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

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

提供了更多详细信息,请参阅 JNI 程序员指南中的“释放引用”。


答案 2

推荐