解决方案 »
- 数据库有数据时怎样发送到客户端
- 为什么android要使用跨进程通信?
- TableLayout里的元素为什么宽度没有占满父控件
- android 开发现在工资高吗?有前途吗?我是做web开发,想转android开发
- android的xml问题
- 安卓图片缩放后定位的问题
- 网易新闻的左右滑动切换页签效果
- jni里面fork出来的子进程阻塞了,导致主程序apk退出的时候调用System.exit(0);会卡死
- 手机通信也是用套接字吗?都用什么协议?和电脑一样吗?
- AndroidStudio 3.0 特别慢怎么办?
- 切换fragment时如何刷新fragment里的内容
- qq空间评论功能的实现细节(android版qq)
查了一些资料,得到的结论是在java线程中不能使用AttachCurrentThread、DetachCurrentThread方法来获取JNIEnv。
估计你调用DetachCurrentThread函数的地方在java线程中,即在java调用C++代码时在C++代码中调用了AttachCurrentThread方法来获取JNIEnv,此时JNIEnv已经通过参数传递进来,你不需要再次AttachCurrentThread来获取。在释放时就会报错。
我使用的方法是通过下面的函数来获取JNIEnv,还没有严格经过验证,仅供参考。
typedef enum _GET_JNIENV_STATUS{
GET_FAIL = 0,
GET_SUCCES_NOATTACH,
GET_SUCCES_ATTCH,
}Get_JNIEnv_Status;
static Get_JNIEnv_Status getJNIEnv(JNIEnv *env)
{
Get_JNIEnv_Status GetStatus = GET_FAIL;
int status = myVm->GetEnv((void **) &env, JNI_VERSION_1_4);
if(status < 0) {
LOGD("callback_handler:failed to get JNI environment assuming native thread");
status = myVm->AttachCurrentThread(&env, NULL);
if(status < 0) {
LOGE("callback_handler: failed to attach current thread");
return GetStatus;
}
GetStatus = GET_SUCCES_ATTCH;
}
else
{
GetStatus = GET_SUCCES_NOATTACH;
}
return GetStatus;
}当返回值为GET_SUCCES_ATTCH时,需要调用DetachCurrentThread来释放资源。
void *run_task(void *args) { //线程需要执行的东西
JNIEnv* env = NULL;
int n = (*jvm1)->AttachCurrentThread(jvm1,&env, NULL); //从jvm中获取到JNIEnv
if (n == 0) {
jstring msg = (*env)->NewStringUTF(env,"Yes Thread Running.");
(*env)->CallVoidMethod(env, obj1, mid1, msg); //回调JAVA层Callback类中的方法
(*env)->DeleteGlobalRef(env,obj1); //删除引用
(*jvm1)->DetachCurrentThread(jvm1); //这个一定要调用,否则报错,意在取消线程与jvm关联
}
LOGI("44");
}