JNI线程绑定的普通用法
JNIEnv *env = nullptr;
jvm->AttachCurrentThread(&env, nullptr);
env->CallVoidMethod(obj, one rrorMethod, -1);
jvm->DetachCurrentThread();
普通用法的缺陷
如果子线程是在C++中创建的,然后通过以上代码来执行Java回调,则没有任何问题
但如果子线程是在Java代码中创建的,Java调用了C++代码,C++代码再调用Java回调方法,就会有问题
因为C++在调用DetachCurrentThread时,这个方法本身就是运行在Java代码之内的,Java仍然在使用此线程,所以是不可能完成解绑操作的
更完善的做法时,在AttachCurrentThread和DetachCurrentThread前,先判断当前代码块,是否已经和Java线程的运行环境绑定,如果已绑定,则没必要再次AttachCurrentThread或DetachCurrentThread
如果我们不这样做,代码运行时则可能会抛出以下的错误
attempting to detach while still running code
正确的使用姿势
JNIEnv *env = nullptr;
bool detached = jvm->GetEnv((void **) &env, JNI_VERSION_1_6) == JNI_EDETACHED;
if (detached) jvm->AttachCurrentThread(&env, nullptr);
env->CallVoidMethod(obj, one rrorMethod, -1);
if (detached) jvm->DetachCurrentThread();