JNI ERROR(app bug):访问陈旧的本地引用0xbc00021(大小为8的表中的索引8)

Meh*_*san 10 android

从这里购买了绝对初学者和温度转换器应用程序的Android应用程序的hello world应用程序 两者在模拟器上运行正常,但当我尝试在Samsung 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)
Run Code Online (Sandbox Code Playgroud)

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

样品运行良好

设备:备注2​​ Samsung-gt_n7100

IDE:Eclipse版本3.8

操作系统:64位Windows 7

Ale*_*xey 60

因为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;  
}
Run Code Online (Sandbox Code Playgroud)

虽然这段代码运行良好:

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;  
}
Run Code Online (Sandbox Code Playgroud)

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

  • 说真的,这应该放在Android的首页上.我现在想知道有多少本机应用程序可能因为这个问题而随机崩溃,耶稣...... (6认同)
  • 精美的解释.我是否需要在任何类型的关闭功能中释放全局引用? (2认同)