JNI。不同Android OS版本之间的不同行为

时间:2013-04-17 17:02:53

标签: android android-ndk java-native-interface jnienv

我的应用程序运行以下代码:

void BmrDeviceInfo_convertToC(JNIEnv *pEnv, jobject jBmrDeviceInfo, BmrDeviceInfo& cBmrDeviceInfo){

__android_log_print(ANDROID_LOG_INFO, "BEAMER_JNI", "g_classBmrDeviceInfo is = %s", (g_classBmrDeviceInfo == NULL) ? "NULL" : "OK"); //g_classBmrDeviceInfo is initialize on JNI_OnLoad

jfieldID fieldName = pEnv->GetFieldID(g_classBmrDeviceInfo, "m_strName", "Ljava/lang/String;"); // OK for Android 4.2 and crash for Android 3.1 or less

..................................
}

崩溃案例的LogCat输出:

04-17 16:28:44.118: I/BEAMER_JNI(446): g_classBmrDeviceInfo is = OK
04-17 16:28:44.118: W/dalvikvm(446): JNI WARNING: 0x4053dc70 is not a valid JNI reference
04-17 16:28:44.118: W/dalvikvm(446):              in Lcom/xxxxxxx/xxxxxx/controller/CoreController;.Init (Lcom/xxxxxxx/xxxxxx/listviews/DeviceInfo;Ljava/lang/String;)I (GetFieldID)
04-17 16:28:44.118: I/dalvikvm(446): "main" prio=5 tid=1 RUNNABLE
04-17 16:28:44.118: I/dalvikvm(446):   | group="main" sCount=0 dsCount=0 obj=0x4001f1a8 self=0xce48
04-17 16:28:44.118: I/dalvikvm(446):   | sysTid=446 nice=0 sched=0/0 cgrp=default handle=-1345006528
04-17 16:28:44.118: I/dalvikvm(446):   | schedstat=( 276745040 468907344 84 )

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

接受对象的JNI函数需要本地或全局引用。 Pre-ICS这些是原始指针,但在ICS中改为表索引系统。

您不会说出在问题中用于生成输出的版本。十六进制值0x4053dc70看起来像一个原始指针,所以我假设这是pre-ICS。查看错误消息,g_classBmrDeviceInfo似乎无效;解决这个问题的常见方法是无法使用NewGlobalRef将本地引用转换为全局引用。

一般来说,JNI在ICS中变得更加更严格,所以它在4.x中成功但在3.x中失败是特殊的,除非你在玩耍弱全球化。