Java-JNI底层多线程反向调用Java方法

JNI中,每个JVM中的线程拥有一个JNIEnv指针对象,而不可以跨线程访问该对象。对于在底层(C/C++)创建的线程,必须手动挂载到JVM中,才能获取到JNIEnv指针对象,并进行各种对象操作。

代码如下:

首先利用静态变量保存JVM对象

static JavaVM *jvm;
(JNIEnv *)env->GetJavaVM(&jvm);

保存调用JNI的Java类对象

static jobject saveObj;
saveObj = env->NewGlobalRef((jobject)obj);

注意,这里不能直接用赋值操作,必须使用JNIEnv对象创建全局变量,才能拷贝到静态变量中。

将线程挂载在JVM中获取新的JNIEnv对象

JNIEnv *env;
jvm->AttachCurrentThread(&env, NULL);
jclass clazz = env->GetObjectClass(saveObj);
jmethodID methodID = env->GetMethodID(clazz, "initServiceCallback","(Z)V");
env->CallVoidMethod(saveObj, methodID, isSuccess);
jvm->DetachCurrentThread();

注意,这里线程挂载成功后,需要获取其env对象,如果是调用静态函数,可以修改为:

jclass clazz = env->GetObjectClass(saveObj);
env->CallStaticVoidMethod(clazz, methodID, isSuccess);

如果没有进行上述操作,会报错:

JNI ERROR: non-VM thread making JNI calls