12

我从这里为 Absolute Beginners 和 Temperature Converter 应用程序制作了 hello world 应用程序 两者都在模拟器上运行良好,但是当我尝试在三星 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

4

1 回答 1

66

由于 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 对象的静态变量或使对象引用全局。
    也许这里最大的例子之一是保留 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

于 2013-07-03T13:18:13.997 回答