Search code examples
javajava-native-interface

Must I DeleteLocalRef an object I have called NewGlobalRef on?


As we know, creating Java objects in a thread owned by C/C++ we are responsible to call DeleteLocalRef or Push/Pop LocalFrame as needed.

I have some code like

jbyteArray buffer = env->NewByteArray((jsize)requiredSize);
longTermBufferReference = (jbyteArray)env->NewGlobalRef(buffer);

where native code creates a byte array, which it re-uses across multiple threads/calls, once we are done with it, I call DeleteGlobalRef on the buffer.

The question is, must I call DeleteLocalRef on buffer when I'm done, or does the GlobalRef take complete ownership of the object?


Solution

  • In a garbage collected system, there is no such thing as object ownership. There are root object references and object references that are reachable directly or indirectly from the roots. (Weak references are not considered).

    Both JNI local references and JNI global references are root references. Creating additional references does not affect existing references nor remove them from the list of root references.

    So, yes, the local reference must be deleted (just as the global reference must be deleted). You already know that you can do it explicitly with DeleteLocalRef or PopLocalFrame, or, when a JNI native method returns, JNI effectively calls PopLocalFrame automatically.