2013-04-17 83 views
0

我的应用程序运行下面的代码:JNI。不同的Android操作系统版本之间的不同的行为

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) 

感谢您的帮助!

+0

检查这个http://stackoverflow.com/questions/11907832/jni-local-vs-global-reference-is-not-a-valid-jni-reference – Pragnani

+0

看起来像很多改变4 1实现类改变从c https://android.googlesource.com/platform/dalvik/+/gingerbread/vm/Jni.c到C++ https://android.googlesource.com/platform/dalvik/+/master/vm/Jni.cpp而且还有很多更改。看起来最早的版本是4.1.1左右。这可能有点解释你的问题。现在我不是一个很棒的C人,所以你可以看看它,你可以看到它的差异。没有任何东西出现在我身上。 – Jackie

回答

2

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

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

一般来说,JNI变成了更多在ICS中是严格的,所以它很奇特,它会在4.x中成功,但在3.x中失败,除非你玩弄弱的全局变量。

+0

我不确定我是否自己跟着这个,你知道源代码在哪里发生了变化吗? – Jackie

+0

NM这解释了它更多一点... http://android-developers.blogspot.com/2011/11/jni-local-reference-changes-in-ics.html。所以基本上他使用的是ref,当他以后试图访问它时(在ICS之前),该对象已经被GC移动,因此是无效的。基本上是这样吗? – Jackie

+1

达尔维克GC,至少通过软糖,不移动物体。 Class对象永远不会被丢弃,所以这个失败看起来像是一个糟糕的全局或者只是一个完全不好的指针。 ICS之前的CheckJNI实现试图通过在全局和本地ref表中搜索引用来检查对象的有效性,但是有可能“伪造”这一点。 > = ICS“间接引用”方法更加准确,并且由于不再提供原始指针,因此允许GC移动对象(这是工作的主要动机)要容易得多。 – fadden

相关问题