调用CallStaticObjectMethod报出JNI DETECTED ERROR IN APPLICATION: jclass is an invalid local reference:

最近遇到一个JNI的问题,一套代码在Android上首次运行是OK的,但是在第二次运行之后设备就会崩溃,查看logcat发现报JNI DETECTED ERROR IN APPLICATION错误。

  (1)错误:
 accessed stale local reference 0x57200019 (index 6 in a table of size 6)
 JNI DETECTED ERROR IN APPLICATION: jclass is an invalid local reference    in call to CallStaticObjectMethod  from void com.org.vincent.ccalljava.JNI.getTime()
JNI DETECTED ERROR IN APPLICATION: calling static method xxxx with CallxxxxMethodV in call to CallxxxxMethodV

综合上面这个错误显示是CallStaticObjectMethod 的jclass 参数非法引用,网上找了一些相关问题的帖子,说明在JNI中有三种不用的引用方式,不同方式有不同的生命周期。结合本地代码,发现最有可能的就是jclass 实例不能用局部引用,必须使用全局引用保持jclass实例在函数退出后还具有生命周期。

改变前:

 if(JNI == NULL) {

        JNI = (*jniEnv)->FindClass(jniEnv,"com/org/vincent/ccalljava/JNI");
        if(JNI == NULL){
            return -1;
        }

        __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitProvider Begin  2 ok" );
    }

改成后:

 if(JNI == NULL) {
        jclass localRef;
        localRef = (*jniEnv)->FindClass(jniEnv,"com/org/vincent/ccalljava/JNI");
        if(JNI == NULL){
            return -1;
        }
        //创建一个jclass 的全局引用
        JNI=(*jniEnv)->NewGlobalRef(jniEnv,localRef);
        __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitProvider Begin  2 ok" );
    }

JNI是在jni中定义的全局变量,如果这个函数一旦执行完退出,那么JNI指向的jclass类型内存可能会被GC回收,那么JNI就指向非法地址。
事后验证判定是对的
参考:blog

你可能感兴趣的:(android错误,AndroidNDK)