(* vm) -> Сбой по умолчанию GetEnv только на устройствах HTC - PullRequest
1 голос
/ 10 ноября 2011

В настоящее время я работаю над большим проектом с несколькими потоками в собственной среде. Поэтому мне нужен вызов (* vm) -> GetEnv, чтобы получить текущий активный JNIEnv для собственного потока. Потоки присоединяются при создании, но я добавил аварийное переключение в методе, который вызывает GetEnv:

void get_jni_env(void **e) {
    JNIEnv *env = malloc(sizeof(JNIEnv *));

    if((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK) {
        __android_log_write(ANDROID_LOG_ERROR, "Call to GetEnv from a unattached native thread. Trying to attach thread.");
        if((*vm)->AttachCurrentThread(vm, &env, NULL) != JNI_OK) {
            __android_log_write(ANDROID_LOG_ERROR, "Failed to receive any jni environment. Crashing soon");
        }
    }

    *e = env;
}

При прохождении вы видите, что вызов (* vm) -> GetEnv segfaults:

jni_get_long (ctx=0x40525080, key=0x804215e0 "hm") at jni/jni.c:50
50      GET_JNI_ENV(&env);
(gdb) s
get_jni_env (e=0xbec603e8) at jni/../../../../core/android/util.c:159
159     if((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK) {
(gdb) n
156 void get_jni_env(void **e) {
(gdb) 
157     JNIEnv *env = malloc(sizeof(JNIEnv *));
(gdb) 
159     if((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK) {
(gdb) 

Program received signal SIGSEGV, Segmentation fault.
0xaca43510 in ?? ()  ← this is somewhere on the heap

Этот же код прекрасно работает на устройствах Samsung и Sony Ericsson, а также в эмуляторе. У меня нет идей для этой конкретной ошибки. Я также протестировал устройство HTC с CyanogenMod 7.1, которое должно быть очень похоже на Android AOSP, и даже там оно вылетает в той же точке.

Ответы [ 2 ]

1 голос
/ 22 ноября 2011

Не могу понять, почему вы неправильно размещаете переменную JNIEnv? Android делает это за вас. В любом случае, вот мой код, который отлично работает на моем HTC Desire:

JNIEnv *GetJEnv() {
  JNIEnv *res;
  if (jvm->GetEnv((void **)&res,JNI_VERSION_1_6)==JNI_EDETACHED)
    jvm->AttachCurrentThread(&res,NULL);
  return res;
}
0 голосов
/ 29 августа 2017

JNIEnv *env = malloc(sizeof(JNIEnv *));

это неправильно .

Он выделяет память, которая может содержать указатель на объект JNIEnv, а не объем памяти для самого объекта JNIEnv.

Это должно быть

JNIEnv *env = malloc(sizeof(JNIEnv));

или даже лучше:

JNIEnv *env = malloc(sizeof( *env ));

«Отлично работает» на других платформах не означает, что это правильно.

...