Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NewGlobalRef/DeleteGlobalRef when returning object created in JNI

When returning reference to object created in JNI method to Java, should we return result of NewGlobalRef call on created object? And, respectively, later, when object no more required in Java, do we need to call JNI method to do DeleteGlobalRef on the reference passed from Java?

Or NewGlobalRef/DeleteGlobalRef required only to hold references to Java object inside JNI, between JNI methods calls, and if we simply return created object to Java we dont need to do NewGlobalRef/DeleteGlobalRef calls?

I've seen such thing in a large open source project:

extern "C" JNIEXPORT jobject JNICALL
Java_foo_bar_Baz_create(JNIEnv* env, jclass, jint size) {
    void* buf = malloc(size);
    jobject obj = env->NewDirectByteBuffer(buf, size);
    return env->NewGlobalRef(obj);
}

extern "C" JNIEXPORT void JNICALL
Java_foo_bar_Baz_free(JNIEnv* env, jclass, jobject jbuffer) {
    void* buf = env->GetDirectBufferAddress(jbuffer);        
    free(buf);
}

It return result of NewGlobalRef call on created NewDirectByteBuffer object, and later, when object no more required in Java, there is a call to JNI method that does not call DeleteGlobalRef, but just call free() on the native buffer address.

like image 400
Playful Curiosity Avatar asked Apr 27 '15 09:04

Playful Curiosity


1 Answers

When returning reference to New[Type]Array, or other object created in JNI method to Java, should we return result of NewGlobalRef call on created object?

Only if you also want to retain that reference for use in future JNI calls without receiving it again as a JNI method parameter.

And respectively, later, when object no more required in Java, do we need to call JNI method to do DeleteGlobalRef on the reference passed from Java?

Only if you called NewGlobalRef() on it.

Or NewGlobalRef/DeleteGlobalRef required only to hold references to Java object inside JNI, between JNI methods calls

Absolutely correct.

and if we simply return created object to Java we dont need to do NewGlobalRef/DeleteGlobalRef calls?

Correct again.

I saw returning result of NewGlobalRef on created NewDirectByteBuffer object (real buffer allocated via malloc()), in large open source project. And later, when object no more required in Java, there is a call to JNI method, that don't do DeleteGlobalRef, but just call free() on the native buffer address obtained from GetDirectBufferAddress.

That would constitute a leak of the DirectByteBuffer object, but not of its native buffer.

like image 103
user207421 Avatar answered Nov 04 '22 21:11

user207421