JNI访问ContactsContract$Data的EXTRA_ADDRESS_BOOK_INDEX字段报错求助
问题分析与解决方案
嘿,这个问题的核心原因其实很简单——你找错了常量所属的类!
咱们来拆解一下:
- 你成功访问的
VISIBLE_CONTACTS_ONLY确实是android.provider.ContactsContract$Data(也就是ContactsContract.Data内部类)的静态字段,所以你的JNI代码找对了类,自然能正常工作。 - 但
EXTRA_ADDRESS_BOOK_INDEX这个常量并不属于ContactsContract.Data内部类,它是外层android.provider.ContactsContract类的静态成员!你错误地在ContactsContract$Data类里查找这个字段,导致GetStaticFieldID返回了无效的fieldID,后续调用GetStaticObjectField就会触发JNI错误崩溃。
修正后的JNI代码
把查找的类改成android.provider.ContactsContract就可以解决问题了:
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = nullptr; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; // 处理获取环境失败的情况 } // 注意这里的类是外层的ContactsContract,不是内部类Data jclass clazz = env->FindClass("android/provider/ContactsContract"); if (clazz == nullptr) { return JNI_ERR; // 处理找不到类的情况 } jfieldID fieldID = env->GetStaticFieldID(clazz, "EXTRA_ADDRESS_BOOK_INDEX", "Ljava/lang/String;"); if (fieldID == nullptr) { env->DeleteLocalRef(clazz); return JNI_ERR; // 处理找不到字段的情况 } jobject field = env->GetStaticObjectField(clazz, fieldID); // 这里可以添加对field的使用逻辑,比如转换成C字符串等 env->DeleteLocalRef(clazz); env->DeleteLocalRef(field); // 记得释放局部引用,避免内存泄漏 return JNI_VERSION_1_6; }
额外建议
- 永远不要忽略JNI调用的返回值检查!比如
FindClass、GetStaticFieldID都可能返回nullptr,提前处理这些情况可以避免莫名其妙的崩溃,也方便调试。 - 记得释放JNI局部引用,尤其是在JNI_OnLoad这种生命周期较长的方法里,防止内存泄漏。
补充一下你遇到的报错信息:
java_vm_ext.cc:534] JNI DETECTED ERROR IN APPLICATION: static jfieldID 0x6fd191b0 not valid for class java.lang.Class<android.provider.ContactsContract$Data>
这个报错其实已经提示你了:你拿到的fieldID对于ContactsContract$Data类是无效的,本质就是因为这个字段根本不在这个类里。
内容的提问来源于stack exchange,提问作者Darin Dimitrov
相关产品推荐
相关产品推荐

