I have an Android project with JNI. In the CPP file which implements a listener class, there is a callback x() . When x() function is called, I want to call another function in a java class. However, in order to invoke that java function, I need to access JNIEnv*.
I know that in the same cpp file of the callback, there is a function:
static jboolean init (JNIEnv* env, jobject obj) {...}
Should I save in the cpp file JNIEnv* as member variable when init(..)
is called? and use it later when the callback happens?
Sorry but I am a beginner in JNI.
Caching a
JNIEnv*
is not a particularly good idea, since you can't use the sameJNIEnv*
across multiple threads, and might not even be able to use it for multiple native calls on the same thread (see http://android-developers.blogspot.se/2011/11/jni-local-reference-changes-in-ics.html)Writing a function that gets the
JNIEnv*
and attaches the current thread to the VM if necessary isn't too difficult:The way you'd use it is:
You could wrap this in a class that attaches upon construction and detaches upon destruction, RAII-style:
Edit: Sometimes you might have a long-ish running native thread that will need a
JNIEnv*
on multiple occasions. In such situations you may want to avoid constantly attaching and detaching the thread to/from the JVM, but you still need to make sure that you detach the thread upon thread destruction.You can accomplish this by attaching the thread only once and then leaving it attached, and by setting up a thread destruction callback using
pthread_key_create
andpthread_setspecific
that will take care of callingDetachCurrentThread
.If
__cxa_thread_atexit
is available to you, you might be able to accomplish the same thing with somethread_local
object that callsDetachCurrentThread
in its destructor.