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

时间:2013-02-08 04:39:43

标签: android

我从书籍Android应用程序中为Absolute Beginners和Temperature Convertor app from here制作了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)

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

样品运行良好

  

设备:注意2 Samsung-gt_n7100

     

IDE:Eclipse版本3.8

     

操作系统:64位Windows 7

1 个答案:

答案 0 :(得分: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对象的静态变量或在存储它们之前使作业引用全局化。 也许最重要的例子是保持jclass对象。通常,您将在JNI_OnLoad期间初始化静态jclass变量,因为只要应用程序正在运行,类对象就会保留在内存中。

  3. 此代码将导致崩溃:

    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