Android ICS:JNI错误尝试使用陈旧的本地引用0x1

时间:2012-04-02 14:09:44

标签: android opengl-es android-ndk java-native-interface

将我的手机升级到android 4.03后,我的游戏再次打开,它只是在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 个答案:

答案 0 :(得分:29)

“陈旧的本地引用”错误意味着您在JNI调用之间保存对某个Java对象的本地引用;您需要使用NewGlobalRef方法将该引用转换为全局引用,然后再执行任何会导致引用超出一个JNI调用范围的内容。

虽然严格来说这始终是必要的 - 这是在JNI规范中 - 只有冰淇淋三明治才会导致Android平台出现问题。

答案 1 :(得分:20)

虽然Ernest的answer在技术上是正确的,但对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()

这是一个容易犯的错误,因为booleanBoolean之间的唯一区别是大写。

  • boolean是一种基本类型,在JNI中表示为boolean
  • java.lang.Boolean,也称为Boolean,是一种类型,在JNI中表示为jobject

foobar返回后,Java VM会将JNI_TRUE值(0x1)视为引用java.lang.Boolean对象,这将导致此致命错误。

答案 2 :(得分:13)

@Ernest和@Ilya是正确的。请注意,问题也以其他方式表现出来,而不仅仅是签名不匹配。我遇到了另一个非常具体的案例,在Android'团队的博客中解释了here部分:

  

Bug:错误地假设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));

经过大量的讨论,这为我解决了这个问题。

答案 3 :(得分:1)

这是欧内斯特答案的一个变种,而不是传递布尔值甚至布尔值作为调用方法的参数,我传递了文字真实(是的,当我发现时,我确实反复踢过)当然这有值0x1。

答案 4 :(得分:0)

虽然没有质疑其他答案的有效性,但我却浪费了数小时追逐这些错误。在我的情况下,他们真的很神秘,但我只能责怪自己:

  

10-16 12:24:18.722:E / dalvikvm(1204):JNI ERROR(app bug):尝试使用陈旧的全局引用0x26
  10-16 12:24:18.722:E / dalvikvm(1204):VM中止

对我来说,这意味着我没有在清单中请求正确的许可。

答案 5 :(得分:0)

在我的情况下,我在调用NewObject时错过了传递构造函数所需的一些参数(也可能适用于调用方法)的问题。