我从
Android应用程序的绝对初学者和温度转换器应用程序
from here创建了你的世界应用程序
两个在仿真器上运行正常,但是当我尝试在Samsung Note 2上运行时,LogCat上出现错误
两个在仿真器上运行正常,但是当我尝试在Samsung 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)
样品运行正常
device: note 2 Samsung-gt_n7100
IDE:Eclipse version 3.8
OS: 64bit Windows 7
解决方法
由于android 4.0垃圾收集器已更改.现在它在垃圾回收过程中移动对象,这可能会导致很多问题.
想象一下,你有一个静态变量指向一个对象,然后这个对象被gc移动.由于android使用java对象的直接指针,这意味着您的静态变量现在指向内存中的随机地址,不被任何对象占用或被不同排序对象所占用.这几乎可以保证您下次使用此变量时会获得EXC_BAD_ACCESS.
所以android给你的JNI错误(应用程序错误)错误,以防止你得到不可调用的EXC_BAD_ACCESS.现在有两种方法来避免这个错误.
>您可以将清单中的targetSdkVersion设置为11或更低版本.这将启用JNI错误兼容性模式并防止任何问题.这就是为什么你的旧例子正在工作的原因.
>您可以通过调用env-> NewGlobalRef(ref)来避免使用指向java对象的静态变量或使jobject引用全局,然后再存储它们.
也许在这里最大的例子是保留jclass对象.通常,您将在JNI_OnLoad期间初始化静态jclass变量,因为只要应用程序正在运行,类对象保留在内存中.
此代码将导致崩溃:
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提供的链接