Ответ 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