【问题标题】:JNI ERROR (app bug): accessed stale local reference 0xbc00021 (index 8 in a table of size 8)JNI 错误(应用程序错误):访问过时的本地引用 0xbc00021(大小为 8 的表中的索引 8)
【发布时间】:2013-02-08 04:39:42
【问题描述】:

我从书籍 Android 应用程序为绝对初学者和温度转换器应用程序制作了 hello world 应用程序from here 两者都在模拟器上运行良好,但是当我尝试在三星 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)

两个应用程序都打开显示带有标题的布局,但不显示布局中的任何其他视图

样品运行良好

设备:note 2 Samsung-gt_n7100

IDE:Eclipse 3.8 版

操作系统:64 位 Windows 7

【问题讨论】:

标签: android


【解决方案1】:

自从 android 4.0 垃圾收集器发生了变化。现在它在垃圾收集期间移动对象,这可能会导致很多问题。

假设你有一个静态变量指向一个对象,然后这个对象被 gc 移动了。由于 android 使用 java 对象的直接指针,这意味着您的静态变量现在指向内存中的随机地址,未被任何对象占用或被不同类型的对象占用。这几乎可以保证您下次使用此变量时将获得 EXC_BAD_ACCESS。

所以 android 给你 JNI ERROR (app bug) 错误以防止你得到不可调试的 EXC_BAD_ACCESS。现在有两种方法可以避免这个错误。

  1. 您可以将清单中的 targetSdkVersion 设置为版本 11 或更低版本。这将启用 JNI 错误兼容模式并完全防止任何问题。这就是您的旧示例有效的原因。

  2. 您可以通过调用 env->NewGlobalRef(ref) 在存储它们之前避免使用指向 java 对象的静态变量或使 jobject 引用全局化。
    也许这里最大的例子之一是保留 jclass 对象。通常,您将在 JNI_OnLoad 期间初始化静态 jclass 变量,因为只要应用程序正在运行,类对象就会保留在内存中。

这段代码会导致崩溃:

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;  
}

有关更多示例,请参阅 Marek Sebera 提供的链接:http://android-developers.blogspot.cz/2011/11/jni-local-reference-changes-in-ics.html

【讨论】:

  • 说真的,这应该出现在 Android 的首页上。我现在想知道有多少本机应用程序会因为这个问题而随机崩溃,耶稣...
  • @Alexey mate 我是 android 新手,面临同样的问题 stackoverflow.com/questions/21423036/… 请告诉我如何实现你的代码..我从过去 3 周开始纠正它:(
  • @ManishYadav sqlite 库的 jni 包装器可能与我在这里谈论的相同的错误,但如果不查看 jni(c 端)包装器本身,我不能肯定地说。您真的应该将 java 端和 c 端 jni 代码附加到您的问题中。另外,您是否考虑过在 sqlite 周围使用 android 标准包装器?它速度很快,几乎可以满足任何需求(非英语本地化搜索、自定义索引和其他很少使用的东西除外)。
  • @Alexey 感谢大量好友的建议,现在我已经上传了“c”文件,请找到代码。
  • 解释得很漂亮。我需要在任何类型的关闭函数中释放全局引用吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多