Android ICS: ошибка JNI при попытке использовать устаревшую локальную ссылку 0x1 - PullRequest
19 голосов
/ 02 апреля 2012

После обновления моего телефона до android 4.03 ics моя игра больше не открывается, она просто закрывается без сообщений об ошибках на deviCe и с этим на eclipse

04-02 16:55:27.672: E/dalvikvm(26884): JNI ERROR (app bug): attempt to use stale local reference 0x1
04-02 16:55:27.672: E/dalvikvm(26884): VM aborting

Моя игра в основном написана на Java, но некоторые ее частия нахожусь в c, и это было, я думаю, что проблема (не очень трудно выяснить, так как она говорит, JNI ERROR :))

Конечно, я не знаю, где проблема, поэтому я не даю никакого кода

У меня не было этой проблемы на Android 2.3

Я не знаю, помогает ли это, но иногда я получаю эту ошибку слишком часто

04-02 16:55:26.061: E/Adreno200-ES11(26884): <qglDrvAPI_glTexImage2D:1913>: GL_STACK_UNDERFLOW

Ответы [ 6 ]

29 голосов
/ 02 апреля 2012

Ошибка «устаревшая локальная ссылка» означает, что вы сохраняете локальную ссылку на некоторый объект Java между вызовами JNI;вам нужно преобразовать эту ссылку в глобальную ссылку, используя метод NewGlobalRef, прежде чем делать что-либо, что заставит ссылку сохраниться вне области действия одного вызова JNI.

Хотя строго это было всегда необходимо - это в спецификации JNI - только после Ice Cream Sandwich это на самом деле вызывает проблемы на платформе Android.

21 голосов
/ 10 октября 2012

Хотя ответ Эрнеста технически верен, устаревшая локальная ссылка на что-то вроде 0x1 должна подсказывать вам, что Java VM пытается использовать что-то, что не является объектом Java, в качестве объекта Java.

Например, предположим, что ваша JNI-функция:

JNI_EXPORT jboolean foobar(JNIEnv *env, jobject self) {
  ...
  return JNI_TRUE;
}

, но вы ошибочно объявляете Java-аналог как public native Boolean foobar() вместо public native boolean foobar().

Это простая ошибка, которую можно сделать, поскольку единственная разница между boolean и Boolean заключается в использовании заглавных букв.

  • boolean, примитивный тип, представлен в JNI как boolean
  • java.lang.Booleanтакже известный как Boolean, является типом класса, который представлен в JNI как jobject

По возвращении из foobar виртуальная машина Java будет обрабатывать значение JNI_TRUE (0x1)как если бы он ссылался на объект java.lang.Boolean, что приведет к этой фатальной ошибке.

13 голосов
/ 24 января 2014

@ Эрнест и @ Илья верны.Обратите внимание, что проблема проявляется и в других отношениях, а не только в несоответствии сигнатур.Есть еще один очень специфический случай, с которым я столкнулся, который был объяснен здесь в блоге команды Android в разделе:

Ошибка: ошибочно предполагая FindClass ()возвращает глобальные ссылки

FindClass () возвращает локальные ссылки.Многие люди считают иначе.В системе без выгрузки классов (например, Android) вы можете рассматривать jfieldID и jmethodID, как если бы они были глобальными.(На самом деле они не являются ссылками, но в системе с выгрузкой классов есть подобные проблемы времени жизни.) Но jclass - это ссылка, и FindClass () возвращает локальные ссылки.Распространенный шаблон ошибок - «статический jclass».Если вы вручную не превратили свои локальные ссылки в глобальные ссылки, ваш код не работает.

По сути, я кэшировал jclass, возвращаемый FindClass, в глобальную переменную как есть, но получаетсяЭто значение (по состоянию на Android 4?) теперь является localref.В результате мне пришлось преобразовать его в globalref, например, так:

jclass jc = env->FindClass(callbacks.name);
// Since Android ICS, class references are not global so we need to peg a
// global reference to the jclass returned by FindClass(), otherwise we get
// following error in the log:
// "JNI ERROR (app bug): attempt to use stale local reference 0xHHHHHHHH".
callbacks._class = static_cast<jclass>(env->NewGlobalRef(jc));

После большого количества головных болей это решило проблему для меня.

1 голос
/ 12 июня 2014

Это вариант ответа Эрнеста, вместо того, чтобы передать логическое или даже логическое значение в качестве аргумента методу вызова, я передал буквальное значение true (да, я действительно ударил себя несколько раз, когда нашел это), что, конечно, имеет значение 0x1.

0 голосов
/ 04 октября 2018

В моем случае я пропустил передачу некоторых аргументов, необходимых для конструктора (также может применяться к вызывающим методам) при вызове NewObject.

0 голосов
/ 16 октября 2014

Не оспаривая обоснованность других ответов, я потерял часы, гоняясь за этими ошибками.В моем случае они были действительно загадочными, но я сам виноват:

10-16 12: 24: 18.722: E / dalvikvm (1204): ОШИБКА JNI (ошибка приложения): попыткаиспользовать устаревшую глобальную ссылку 0x26
10-16 12: 24: 18.722: E / dalvikvm (1204): прерывание виртуальной машины

Для меня это означало, что я не запросил правильное разрешение вманифест.

...