Java JNI对象创建和内存管理

Java JNI对象创建和内存管理,java,c++,memory-management,memory-leaks,java-native-interface,Java,C++,Memory Management,Memory Leaks,Java Native Interface,我有以下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(arrayCla

我有以下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;
}
JNIEXPORT作业对象JNICALL Java_com_test_myClass_myMethod(JNIEnv*env,jclass klass){
jclass arrayClass=env->FindClass(“java/util/ArrayList”);
jmethodID initMethod=env->GetMethodID(arrayClass,“,”()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(“世界”);
返回myArray;
}
我是否需要释放在本机代码中创建的对象,还是由GC自动完成?
如果我这样做了,我该如何做,因为我需要将其返回到Java?

您不需要释放在本机代码中创建的Java对象。事实上,你不能。当不再保留引用时,垃圾收集器可以释放该对象

有时,在本机代码中,释放对Java对象的引用很有用。当本机代码包含但不再需要对大型对象或大量引用的引用时,这可以减少内存需求

中的“全局和本地引用”

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

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

我认为应该由本机代码自行管理内存。在这种情况下,我认为您需要添加另一个本机方法来释放分配的对象,当您完成这些对象时,您可以手动调用这些对象。更一般地说,如果你在用JNI做事,那么我希望你准备好面对一个充满伤害的世界。这个答案可能有帮助:@aroth-错了。如果您在JNI中分配Java对象,它们是Java对象,归GC所有。@bmargiles-有道理,但是对于分配非Java对象/内存的本机代码,例如通过调用
malloc()
?@aroth不是关于这个问题的。我阅读了关于释放引用的指南,但我有一个问题:在我最初的帖子中多次调用该方法是否会造成资源耗尽问题?如果是,我在哪里可以释放引用,因为我仍然需要返回它们?本地引用在每次调用后自动释放。您不必显式地这样做,除非1)您已经创建了一个全局引用,或者2)出于链接中描述的原因,需要在调用完成之前释放本地引用。正在复制您返回的引用。myArray和返回的引用点都指向同一个Java对象。新链接:GoogleBooks链接现在也死了。Sun文档可在internet存档中找到:(第5.2节是“释放参考”部分)。将链接从1999年的“程序员指南和规范”更改为当前的在线“Java本机接口规范”。并添加了新链接变成灰尘时的块报价。