Java AttachCurrentThread崩溃

Java AttachCurrentThread崩溃,java,android,c,java-native-interface,Java,Android,C,Java Native Interface,如果调用以下函数,应用程序将崩溃: 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); } vo

如果调用以下函数,应用程序将崩溃:

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(..)中

编辑3:


这个问题已经解决了。。最后的更改包括编辑2+java代码中的一些更改(此处不可见(其中有错误))。

首先,确保参数vm在日志上的
void中正确(JavaVM*vm,int-level,const-char*data)
。我在
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM*vm,void*reserved)
中将vm保存为全局变量,我的代码可以工作:

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
                g_vm = vm;
}
在线程的函数中

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

代码中有问题的地方是在创建线程时。线程函数接受一个指针,而不是两个

因此,您可以给它
VM*
,或者
数据
,或者将它们包装成某种结构

包装示例:

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;
 ...
第二个问题是线程连接:在连接到线程之前无法获取JNIEnv:

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

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

如何检查这是否正确?我正在初始化加载(..)方法。。此外,调用(*vm)->GetEnv(..)能够正常运行,因此它没有为其他线程(从中调用了on_log(..)的)检查GetEnv为null,并且工作正常。。所以vm应该是正确的。。在onload中没有返回任何int。。我正在返回JNI版本2。。因此,在附加调用中,根据调用api docsI,我不能使用NULL,我刚刚向您展示了我的部分代码。要验证vm是否正确,可以注销vm的值。导入android.util.Log;和Log.i(“VM”,String.format(“VM:0x%x”,VM));如果在线程中什么都不做(即:在调用attachJNIEnvToThread后注释掉所有代码),是否仍然会发生崩溃?我删除了所有内容,但它仍然会崩溃。。获取以下内容:/system/lib/libdvm.so(dvmaport+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)