I'm wondering how safe it is to use a local reference created in a native method and returned by that method to the caller.
Here's a simple example:
jobject getAJObject(JNIEnv* jni) {
jobject obj = jni->CallStaticVoidMethod(...); // java method that returns a jobject
return obj;
}
void func(JNIEnv* jni) {
jobject obj = getAJObject(jni);
// Code that uses obj
...
}
I have tested this code and it does work fine, but I'm worried that it's not safe. My understanding from reading the JNI spec is local references are only valid in the stack frame it was created, and are cleaned up when the native method returns. Does this mean that obj can get garbage collected after getAJObject finishes, and while still on the native side without returning back to java?
This article indicates that this code is not safe: http://publib.boulder.ibm.com/infocenter/javasdk/v1r4m2/index.jsp?topic=%2Fcom.ibm.java.doc.diagnostics.142j9%2Fhtml%2Fhandlocref.html
However I still see examples of JNI code that do exactly this! Was hoping for some more clarification.
You can safely use getAJObject() from func(). All garbage collection and local reference management for the native object obj are frozen while the JNI call is under way. Let me address two different scenarios:
If your code calls func() from a Java thread (i.e. if JVM can be found in the call stack), if there was a native Java method that called func() through some chain of calls, then this native method defines the scope of JNI local references frame.
Alternatively, your code calls func() from a native thread, which needed to call jint AttachCurrentThread(JavaVM *vm, void **penv, void *args) or jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args) to obtain JNIEnv* jni. In this case, the scope of local references, etc. remains until this thread calls jint DetachCurrentThread(JavaVM *vm).
Note that in case 2, if the thread dies without call to DetachCurrentThread(), your JVM will crash.
You can also manage local references scope manually, with jint PushLocalFrame(JNIEnv *env, jint capacity) and jobject PopLocalFrame(JNIEnv *env, jobject result).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With