2014-02-06 60 views
3

应用崩溃如果以下函数被调用:AttachCurrentThread崩溃

void on_log(JavaVM* vm, int level, const char *data) 
{ 
    printOnAndroid(level, data); 
    pthread_t loggerThread; 
    pthread_create(&loggerThread, NULL, attachThreadToJavaVMAndPrint, data); 
    pthread_join(loggerThread, NULL); 
} 

void attachThreadToJavaVMAndPrint(JavaVM* vm, const char *data) 
{ 
    int isThreadAttached = attachJNIEnvToThread(vm); 
    if (isThreadAttached == 1) 
    { 
    JNIEnv* env; 
    (*vm)->GetEnv(vm, &env, APP_JNI_VERSION); 

    jclass thisClass = (*env)->GetObjectClass(env, _loggerObject); 
    jmethodID methodId = (*env)->GetMethodID(env, thisClass, "logFromC","(Ljava/lang/String;)V"); 
    if (methodId != NULL) 
    { 
     jstring message = (*env)->NewStringUTF(env, data); 
     (*env)->CallVoidMethod(env, _loggerObject, methodId, message); 
    } 
    (*vm)->DetachCurrentThread(vm); 
    } 
} 

void printOnAndroid(int level, const char* data) 
{ 
    __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "XXXX %i, data %s", level, data); 
} 

int attachJNIEnvToThread(JavaVM* vm) 
{ 
    JNIEnv* env; 
    JavaVMAttachArgs args; 
    args.version = APP_JNI_VERSION; 
    args.name = NULL; 
    args.group = NULL; 
    if ((*vm)->GetEnv(vm, &env, APP_JNI_VERSION) == JNI_EDETACHED) 
    { 
    jint attachResponse = (*vm)->AttachCurrentThread(vm, &env, &args); 
    if ((*vm)->GetEnv(vm, &env, APP_JNI_VERSION) != JNI_OK) 
    { 
     return 0; 
    } 
    } 
    return 1; 
} 

有一个宏:

#define APP_JNI_VERSION JNI_VERSION_1_2 

作为每日志,有一个当attachJNIEnvToThread(..)被称为

崩溃

编辑:

它在linux上成功运行..所以可能是有东西的android特定我不知道的。

编辑2:

改变后的签名:

void * attachThreadToJavaVMAndPrint(void* dataArg) 
    { 
    JavaVM* vm = _vm; 
    const char* data = (const char *)dataArg; 
    int isThreadAttached = attachJNIEnvToThread(vm); 
    if (isThreadAttached == 1) 
    { 
     JNIEnv* env; 
     (*vm)->GetEnv(vm, &env, APP_JNI_VERSION); 

     jclass thisClass = (*env)->GetObjectClass(env, _loggerObject); 
     jmethodID methodId = (*env)->GetMethodID(env, thisClass, "logFromC","(Ljava/lang/String;)V"); 
     if (methodId != NULL) 
     { 
      jstring message = (*env)->NewStringUTF(env, data); 
      (*env)->CallVoidMethod(env, _loggerObject, methodId, message); 
     } 
     (*vm)->DetachCurrentThread(vm); 
    } 
    return 0; 
    } 

这略微改变日志和碰撞是在attachThreadToJavaAndPrint(..)

EDIT 3:

这已经解决了。最终修改包括编辑2 + java代码中的一些更改(在此处不可见(其中存在错误))。

+0

仍然有崩溃:您无法连接到线程之前得到的JNIEnv线程(即:在调用attachJNIEnvToThread之后注释掉所有代码)? – manuell

+0

我删除了一切,但它仍然崩溃..获取以下内容: /system/lib/libdvm.so(dvmAbort + 67) 02-10 12:32:30.654 123-123 /? I/DEBUG:#01 pc 0000cecc /system/lib/libc.so 02-10 12:32:30.654 123-123 /? I/DEBUG:#02 pc 0000e5c0 /system/lib/libc.so(pthread_exit + 80) 02-10 12:32:30.654 123-123 /? I/DEBUG:#03 pc 0000cbd4 /system/lib/libc.so(pthread_create + 208) – singhsumit

回答

1

首先,确保参数vm在void on_log(JavaVM* vm, int level, const char *data)中正确。在功能

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) 
{ 
       g_vm = vm; 
} 

线程

{ 
    ret = g_vm->AttachCurrentThread((JNIEnv **) &env, NULL); 
} 
+0

我该如何检查这是否正确? (*) - > GetEnv(..)能够正常运行,因此它不为空 – singhsumit

+0

我检查了getenv的其他线程(从中on_log(..)是称为),它工作正常..所以虚拟机应该是正确的.. 你没有返回任何int onload .. m返回JNI版本2 ..因此在附加调用中,我不能根据调用api使用NULL docs – singhsumit

+0

我只是向你展示了我的部分代码。要验证虚拟机是否正确,可以注销虚拟机的值。导入android.util.Log;和Log.i(“VM”,String.format(“VM:0x%x”,vm)); – yushulx

1

在你的代码有问题的地方是,当你创建线程:我在JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)保存虚拟机作为一个全局变量,和我的代码可以工作。线程函数需要ONE指针,而不是两个。

因此,您可以给它VM*data,或者将它们包装到某个结构中。包装的

例子:

struct params 
{ 
    JavaVM *vm; 
    char *data; 
}; 

void on_log(JavaVM* vm, int level, const char *data) 
{ 
    struct params params = {vm, data}; 
    printOnAndroid(level, data); 
    pthread_t loggerThread; 
    pthread_create(&loggerThread, NULL, attachThreadToJavaVMAndPrint, &params); 
    pthread_join(loggerThread, NULL); 
} 

void * attachThreadToJavaVMAndPrint(void* arg) 
{ 
struct params *params = arg; 
JavaVM* vm = params->vm; 
const char* data = params->data; 
... 

第二个问题是在线程附件:如果您在做什么

int attachJNIEnvToThread(JavaVM* vm) 
{ 
    JNIEnv* env; 

    return (*vm)->AttachCurrentThread(vm, &env, NULL) ? 1 : 0; 
}