I have a JNI wrapper for Java functions that are called from C... I'm trying to call some methods from different threads and I get an error when trying to get a new copy of the JNIEnv pointer... the code I'm using is below and is called in each method:
JNIEnv* GetJniEnvHandle(){
ThreadInfo();
JNIEnv *envLoc;
//if(Thread::CurrentThread->IsBackground || Thread::CurrentThread->IsThreadPoolThread)
jint envRes = vm->GetEnv((void**)&envLoc, JNI_VERSION_1_4);
if(envRes == JNI_OK){
if(ThreadId != Thread::CurrentThread->ManagedThreadId)
jint res = vm->AttachCurrentThread((void**)&envLoc, NULL);
}else{
Log("Error obtaining JNIEnv* handle");
}
return envLoc;
}
The JVM has already been instantiated and this (and other methods) run when being called from the main/initial thread. When I get a value for envRes it holds a -2 when in a sub-thread.
The JNI interface pointer (JNIEnv *) is only valid in the current thread. You must not pass the interface pointer from one thread to another, or cache an interface pointer and use it in multiple threads.
When talking about JNI, there are two directions: java calling C++, and C++ calling java. Java calling C++ (or C) via the "native" keyword is very fast, around 50 clock cycles. However, C++ calling Java is somewhat slow.
JNI is the Java Native Interface. It defines a way for the bytecode that Android compiles from managed code (written in the Java or Kotlin programming languages) to interact with native code (written in C/C++).
Introduction to Java Native Interface: Establishing a bridge between Java and C/C++ JNI (Java Native Interface) is a foreign function interface that allows code running on JVM to call (or be called by) native applications. Using JNI, one can call methods written in C/C++ or even access assembly language.
Please refer to the documentation to the chapter Attaching to the VM
.
You need to call AttachCurrentThread()
for each native thread at least once before you can use any of the JNI functions.
Thread created in Java are already attached.
So I your example whenever the GetEnv
call fails call AttachCurrentThread()
and you should be fine. Or make sure that whenver you create a sub thread you attach it to the VM.
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