JNI ERROR (ошибка приложения): доступ к устаревшей локальной ссылке 0xbc00021 (индекс 8 в таблице размером 8)

Я сделал приветствие мирового приложения из приложений Android для приложений Absolute Beginners и Temperature Convertor отсюда  Оба работают нормально на эмуляторе, но когда я пытаюсь запустить его на Samsung Note 2, следующая ошибка LogCat

02-08 07:22:18.665: E/dalvikvm(30944): JNI ERROR (app bug): accessed stale local reference 0xbc00021 (index 8 in a table of size 8)
02-08 07:22:18.665: E/dalvikvm(30944): VM aborting
02-08 07:22:18.665: A/libc(30944): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 30944 (oid.temperature)

Оба приложения открывают макет представления с заголовком, но не отображают других видов в макете

Образцы выполняются отлично

: примечание 2 Samsung-gt_n7100

IDE: Eclipse версии 3.8

ОС: 64-битная Windows 7

Ответ 1

Так как сборщик мусора андроид 4.0 был изменен. Теперь он перемещает объект во время сбора мусора, что может вызвать множество проблем.

Представьте, что у вас есть статическая переменная, указывающая на объект, а затем этот объект перемещается gc. Так как андроид использует прямые указатели для объектов Java, это означает, что ваша статическая переменная теперь указывает на случайный адрес в памяти, незанятый каким-либо объектом или занятый объектом разного рода. Это почти гарантирует, что вы получите EXC_BAD_ACCESS в следующий раз, когда используете эту переменную.

Итак, андроид дает вам ошибку JNI ERROR (ошибка приложения), чтобы вы не могли получить undebugable EXC_BAD_ACCESS. Теперь есть две возможности избежать этой ошибки.

  • Вы можете установить targetSdkVersion в своем манифесте на версию 11 или меньше. Это позволит поддерживать совместимость ошибок JNI и вообще предотвращать любые проблемы. Вот почему ваши старые примеры работают.

  • Вы можете избежать использования статических переменных, указывающих на объекты Java, или сделать ссылки на задания глобальными, прежде чем хранить их, вызвав env- > NewGlobalRef (ref).
    Возможно, на самых больших примерах здесь хранятся объекты jclass. Как правило, вы инициализируете переменную static jclass во время JNI_OnLoad, так как объекты класса остаются в памяти до тех пор, пока приложение запущено.

Этот код приведет к сбою:

static jclass myClass;

JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * reserved) {  
    myClass = env->FindClass("com/example/company/MyClass");  
    return JNI_VERSION_1_6;  
}

Пока этот код будет работать нормально:

static jclass myClass;

JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * reserved) {  
    jclass tmp = env->FindClass("com/example/company/MyClass");  
    myClass = (jclass)env->NewGlobalRef(tmp);
    return JNI_VERSION_1_6;  
}

Дополнительные примеры см. в ссылке, предоставленной Мареком Себерой: http://android-developers.blogspot.cz/2011/11/jni-local-reference-changes-in-ics.html