【NDK】JNI线程切换、AttachCurrentThread、DetachCurrentThread

原博地址https://blog.csdn.net/u013718730/article/details/117919622

JNI线程绑定的普通用法

	JNIEnv *env = nullptr;
	jvm->AttachCurrentThread(&env, nullptr);
	env->CallVoidMethod(obj, onErrorMethod, -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, onErrorMethod, -1);
	if (detached) jvm->DetachCurrentThread();

JNIEnv工作原理

JNIEnv封装了JNI在某个线程中的运行环境

当Java加载JNI接口,或者调用C++函数时,会将自己的线程信息通过JNIEnv传递给C++

通过GetEnv,我们可以在C++中获取对应的Java线程运行环境

如果当前C++线程,已经和Java线程运行环境绑定,则将该运行环境的地址赋值给JNIEnv*,否则JNIEnv*置为NULL

如果GetEnv得到的JNIEnv*为NULL,则说明该线程环境一定是由C++代码创建的,没有和Java运行环境绑定

此时我们如果希望Java代码也运行在C++线程中,就需要手动AttachCurrentThread

每个JNIEnv对应一个固定的线程,在调用DetachCurrentThread之前,这个JNIEnv是一直可用的,并且它的代码会一直运行在原先的线程

DetachCurrentThread之后,对应的JNIEnv也会失效,再使用就会报错

对于同一个C++线程,我们DetachCurrentThread后,再AttachCurrentThread,还是会返回原先的JNIEnv,并且继续可用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值