19

I have the following JNI method that creates a collection of Java objects natively, and then return them to 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;
}

Do I need to free the objects created in the native code, or is it done automatically by the GC? If I do, how do I do that, as I need to return it to Java?

Macarse
  • 91,829
  • 44
  • 175
  • 230
nbarraille
  • 9,926
  • 14
  • 65
  • 92
  • I would think that it would be up to the native code to do its own memory management. In this case I'd imagine that you'd need to add another native method that releases the allocated object(s), which you manually call when you are done with them. More generally, if you're doing things with JNI then I hope you're prepared for a world of hurt. This answer may help: http://stackoverflow.com/questions/214699/jni-memory-management-using-the-invocation-api – aroth Feb 20 '12 at 23:34
  • 4
    @aroth - wrong. if you allocate Java object in JNI, they are Java objects, owned by the GC. – bmargulies Feb 20 '12 at 23:38
  • @bmargulies - Makes sense, but what about in the case of native code that allocates non-Java objects/memory, for instance by calling `malloc()`? – aroth Feb 20 '12 at 23:50
  • 2
    @aroth not what this question is about. – bmargulies Feb 20 '12 at 23:51

1 Answers1

16

You do not need to free the Java objects created in the native code. In fact, you cannot. The garbage collector may free the object when no further references remain.

Occasionally it is useful in native code to free references to Java objects. This can reduce memory requirements when the native code holds, but no longer needs, references to large objects or a large number of references.

From: "Global and local references" in the JNI specification.

In most cases, the programmer should rely on the VM to free all local references after the native method returns. However, there are times when the programmer should explicitly free a local reference. Consider, for example, the following situations:

  • A native method accesses a large Java object, thereby creating a local reference to the Java object. The native method then performs additional computation before returning to the caller. The local reference to the large Java object will prevent the object from being garbage collected, even if the object is no longer used in the remainder of the computation.
  • A native method creates a large number of local references, although not all of them are used at the same time. Since the VM needs a certain amount of space to keep track of a local reference, creating too many local references may cause the system to run out of memory. For example, a native method loops through a large array of objects, retrieves the elements as local references, and operates on one element at each iteration. After each iteration, the programmer no longer needs the local reference to the array element.

Additional detail was provided See "Freeing References" in the JNI Programmer's Guide.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
  • I read the guide about Freeing References, but have a question about it: Could calling the method in my initial post a large number of times create a resource exhaustion problem? If yes, where can I free the references, as I still need to return them? – nbarraille Feb 21 '12 at 00:05
  • The local references are freed automatically after each call. You don't have to do it explicitly, unless 1) you've created a global reference, or 2) need to free local references before the call completes, for a reason described in the link. The reference you're returning is being copied. Both myArray and the returned reference point to the same Java object. – Andy Thomas Feb 21 '12 at 14:07
  • New link: http://books.google.co.il/books?id=8M3F_sSSvWkC&pg=PA66&lpg=PA66&dq=JNI+Programmer's+Guide+%22freeing+references%22&source=bl&ots=Ql51VhC4ej&sig=yRVfFCPVmOrMDF_GTQmHETTpCUU&hl=en&sa=X&ei=OPNsUrzkDKbv4gTZvIDwCA&ved=0CDgQ6AEwAg#v=onepage&q=JNI%20Programmer's%20Guide%20%22freeing%20references%22&f=false – Vaiden Oct 27 '13 at 11:07
  • 1
    The google books link is also dead now. Sun docs can be found on the internet archive: http://web.archive.org/web/20070812015712/http://java.sun.com/docs/books/jni/html/refs.html (section 5.2 is the "Freeing References" one). – sam Jan 13 '15 at 16:56
  • Changed the link from the 1999 ''Programmer's Guide and Specification'' to the current, online ''Java Native Interface Specification''. And added a block quote for when the new link turns to dust. – Andy Thomas Jan 13 '15 at 17:48