Переполнение ReferenceNable JNI: как выпустить ObjectArray, содержащий Строки - PullRequest
3 голосов
/ 04 января 2012

У меня очень неприятное время для решения этой проблемы, и документация JNI крайне скудна. Помощь будет принята с благодарностью!

Мне назначен проект в сетевом приложении Android. Нативная сторона хранит информацию о пользователях, к которым вы подключены, и мне нужно отправить этот список пользователей на сторону Java, чтобы обновить информацию пользовательского интерфейса. По сути, мне нужно составить строковый массив и логический массив, который содержит имена и флаги подключенных пользователей, но позже может быть отправлено больше информации. Моя трудность заключается в освобождении и очистке массива Object, содержащего информацию String. Мне не ясно, как это сделать. Вот что у меня есть:

void name_list_cb(struct user_info* user_list, size_t count, void *userdata)
{
    jobject callbacks = (jobject)userdata;
    JNIEnv *env;
    (*g_vm)->GetEnv(g_vm, (void**)&env, JNI_VERSION_1_4);
    jclass cls = (*env)->GetObjectClass(env, callbacks);
    jmethodID method = (*env)->GetMethodID(env, cls, "user_list", "([Ljava/lang/String;[Z)V");

    int i;
    jobjectArray name_list;
    jbooleanArray connected_list;

    name_list = (jobjectArray)(*env)->NewObjectArray(env, count, (*env)->FindClass(env, "java/lang/String"), (*env)->NewStringUTF(env, ""));
    connected_list = (jbooleanArray)(*env)->NewBooleanArray(env, count);
    uint8_t boolean_arr[count];
    for(i = 0; i < count; i++) {
        (*env)->SetObjectArrayElement(env, name_list, i, (*env)->NewStringUTF(env, user_list[i].name));
        boolean_arr[i] = user_list[i].connected;
    }
    (*env)->SetBooleanArrayRegion(env, connected_list, 0, count, (jboolean *)boolean_arr);

    (*env)->CallVoidMethod(env, callbacks, method, name_list, connected_list);
    (*env)->ReleaseBooleanArrayElements(env, connected_list, (jboolean *)boolean_arr, 0);

    for(i = 0; i < count; i++) {
        (*env)->ReleaseStringUTFChars(env, (*env)->GetObjectArrayElement(env, name_list, i), user_list[i].name);
        //(*env)->ReleaseObjectArrayElements(env, name_list, count, 0);
    }

    (*env)->DeleteLocalRef(env, boolean_arr);
    (*env)->DeleteLocalRef(env, name_list);
    (*env)->DeleteLocalRef(env, connected_list);
    (*env)->DeleteLocalRef(env, cls);
}

Я получаю либо «переполнение ссылочной базы данных», либо «сигнал 11 (SIGSEGV), ошибка addr deadbaad». Переполнение / утечка памяти является основной проблемой. По сути, я не выпускаю UTFChars и элементы Object. Хотя я видел ссылки на него в Интернете, моя версия JNI не имеет ReleaseObjectArrayElement [s]. Я изучал, как это сделать, но пока не повезло!

Ответы [ 2 ]

1 голос
/ 06 января 2014

Я думаю, что проблема в (* env) -> DeleteLocalRef (env, boolean_arr);потому что boolean_arr является переменной стека функции C.

0 голосов
/ 04 января 2012
typedef jarray          jobjectArray;   
void        (*DeleteLocalRef)(JNIEnv*, jobject);  

Так что я думаю, что использование DeleteLocalRef может освободить jobjectArray.Или вы можете просто создать jobjectArray только один раз в методе инициализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...