技术CTO-关注编程入门知识,提供编程入门教程

您的位置: 首页 > 移动开发 > android > 正文

android Jni开发DetachCurrentThread使用报错

来源: 技术CTO 阅读:

(g_jvm)->AttachCurrentThread(&env, NULL) != JNI_OK 后使用 (g_jvm)->DetachCurrentThread();程序报错
log如下
E/dalvikvm(6848): ERROR: detaching thread with interp frames (count=13)
 I/dalvikvm(6848): "main" prio=5 tid=1 RUNNABLE
 I/dalvikvm(6848):   | group="main" sCount=0 dsCount=0 obj=0x40eb24c0 self=0x7d0788 
I/dalvikvm(6848):   | sysTid=6848 nice=0 sched=0/0 cgrp=default handle=1074890076 
I/dalvikvm(6848):   | schedstat=( 381818920 438359929 2441 ) utm=26 stm=12 core=0 
I/dalvikvm(6848):   at com.shorigo.libs.Common.Login(Native Method)
。。。
I/dalvikvm(6848):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809)
I/dalvikvm(6848):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576)
I/dalvikvm(6848):   at dalvik.system.NativeStart.main(Native Method)
E/dalvikvm(6848): VM aborting
A/libc(6848): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1)求高手解答

jni不熟悉
我是完全的新手,求助啊
我刚才也碰到这个问题。
查了一些资料,得到的结论是在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来释放资源。
http://blog.csdn.net/birdsaction/article/details/17859395 我以前在JNI中使用过线程,不知道是否和你们用的一样。

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");  
}  

^_^ 如果您热爱技术、热爱编程,想与更多的朋友一起交流学习,欢迎加入本站官方QQ群:345733473 ^_^