When my java class loads, I call this jni method to set "listener" from cpp to java (I record audio using cpp and want to pass its bytes to java) :
MyJava.class
setListener(JNIEnv *env, jclass thiz);
myCpp.cpp
setListener(JNIEnv *env, jclass thiz) {
envMyClass = env;
classMyClass = thiz;
// I read that I need these 2 lines in order to connect the java thread to the cpp thread
env->GetJavaVM(&javavm);
GetJniEnv(javavm, &envCamera);
return 0;
}
bool GetJniEnv(JavaVM *vm, JNIEnv **env) {
bool did_attach_thread = false;
*env = nullptr;
// Check if the current thread is attached to the VM
auto get_env_result = vm->GetEnv((void**)env, JNI_VERSION_1_6);
if (get_env_result == JNI_EDETACHED) {
if (vm->AttachCurrentThread(env, NULL) == JNI_OK) {
did_attach_thread = true;
} else {
// Failed to attach thread. Throw an exception if you want to.
}
} else if (get_env_result == JNI_EVERSION) {
// Unsupported JNI version. Throw an exception if you want to.
}
return did_attach_thread;
}
and the in myCpp.cpp thread I'm trying to call:
if (envMyClass != nullptr && classMyClass != nullptr && javavm != nullptr) {
LOGD("000");
jmethodID javaMethod = envMyClass->GetStaticMethodID(classMyClass, "myJavaFunction", "()V");
LOGD("001");
envMyClass->CallStaticVoidMethod(classMyClass, javaMethod);
}
and it crashes on the line of "jmethodId javaMethod.."
myJavaFunction is a method in MyJava class:
public static void myJavaFunction() {
Log.d("my_log", "jni callback");
}
the crash:
Abort message: 'JNI DETECTED ERROR IN APPLICATION: a thread (tid 12346 is making JNI calls without being attached
in call to GetStaticMethodID'
Any idea how to fix it?
I've noticed a few things:
jclass thizto a global variableclassMyClass. To do so, you should useclassMyClass = env->NewGlobalRef(thiz), otherwise the class reference will not be valid (reference).GetJniEnvbut you do not check its result and therefore you do not actually know whether the current thread has attached successfully.setListener, save the env to a global variable, and then use that variable at another point in your code. Could it be that you are switching thread context somewhere in between? You could do the following to make sure the current thread is really attached:jmethodID javaMethod = thisEnv->GetStaticMethodID(classMyClass, "myJavaFunction", "()V");only once initially and store the jmethodID in a global variable. jmethodIDs are valid across envs.