使用JNIEnv全局变量调用FindClass()等函数发生crash
[Crash Log]
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x98 Stack frame D/CrashAnrDetector( 859): #00 pc 000b16f4 /system/lib/libart.s o (art::JniAbort(char const*, char const*)+47) Stack frame D/CrashAnrDetector( 859): #01 pc 000b2045 /system/lib/libart.s o (art::JniAbortF(char const*, char const*, ...)+60) Stack frame D/CrashAnrDetector( 859): #02 pc 000b4d9f /system/lib/libart.s o (art::ScopedCheck::ScopedCheck(_JNIEnv*, int, char const*)+334) <span style="color:#FF0000;">Stack frame D/CrashAnrDetector( 859): #03 pc 000b5e35 /system/lib/libart.s o (art::CheckJNI::FindClass(_JNIEnv*, char const*)+20)</span> <span style="color:#FF0000;">Stack frame D/CrashAnrDetector( 859): #04 pc 0003f554 /data/app/com.nation sky.rc.samsung-1/lib/arm/librc.so: Routine _JNIEnv::FindClass(char const*) at D:</span> /dev/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/jni.h:519 Stack frame D/CrashAnrDetector( 859): #05 pc 0007c174 /data/app/com.nation sky.rc.samsung-1/lib/arm/librc.so: Routine event_handler at E:MDMRemoteControl l-sansang2RemoteControll-sansang/jni/remotecontroll/remotecontroll.cpp:35625 Stack frame D/CrashAnrDetector( 859): #06 pc 000662b8 /data/app/com.nation sky.rc.samsung-1/lib/arm/librc.so: Routine call_user at E:MDMRemoteControll-sa
[Crash原因分析]
出错的代码:
jclass remotedesktopclass = sJniEnv->FindClass("com/xxx/xxx/xxx/xxx");
sJniEnv是一个全局变量,但其实不应该全局保存JNIEnv。
这是一个和thread紧密关联的变量,在其他线程中使用就会crash。
【参考】
http://blog.csdn.net/freechao/article/details/7692239
【解决方式】
1.参考了第一篇文章,保存一个JavaVM全局变量,然后再其他线程中使用AttachCurrentThread(),代码如下:
JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, __null }; JNIEnv* jniEvn = __null; int res = javaVm->AttachCurrentThread(&jniEvn, &args); jclass tmp = jniEvn->FindClass("com/xxx/xx/xx/xxxxx");
2.但这么做仍然后crash,是说4.0上回收机制有改变,需要使用NewGlobalRef()生成全局变量才能用
remotedesktopclass = (jclass)jniEnv->NewGlobalRef(tmp);
3.上面两部修改后其实还是不行,Log如下:
Line 2149: F/art ( 1223): sart/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: <span style="color:#FF0000;">JNI NewGlobalRef called with pending exception "java.lang.ClassNotFoundException" thrown in unknown throw location</span> Line 2151: F/art ( 1223): sart/runtime/check_jni.cc:65] in call to NewGlobalRef Line 2153: F/art ( 1223): sart/runtime/check_jni.cc:65] "keyPress" prio=5 tid=14 Runnable Line 2155: F/art ( 1223): sart/runtime/check_jni.cc:65] | group="main" sCount=0 dsCount=0 obj=0x12ccb080 self=0xb7c98350 Line 2157: F/art ( 1223): sart/runtime/check_jni.cc:65] | sysTid=1271 nice=0 cgrp=apps/bg_non_interactive sched=0/0 handle=0xb7c94b20 Line 2159: F/art ( 1223): sart/runtime/check_jni.cc:65] | state=R schedstat=( 1043961255 45210048 198 ) utm=94 stm=10 core=1 HZ=100
最终将NewGlobalRef()移到主线程后解决此问题。
总结:
修改地方1:
JNIEXPORT void JNICALL Java_xx_xx_xx_xx_xxx(JNIEnv * jniEnv, jobject object, jstring jflowNum, jstring judid){ jniEnv->GetJavaVM(&javaVm); jclass tmp = jniEnv->FindClass("com/nationsky/rc/util/RemoteDesktopUtil"); remotedesktopclass = (jclass)jniEnv->NewGlobalRef(tmp); .............修改地方2:
static void keyPress(int keyCode){ JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, __null }; JNIEnv* jniEvn = __null; int res = javaVm->AttachCurrentThread(&jniEvn, &args); method = jniEvn->GetStaticMethodID(remotedesktopclass, "pressHome", "()V"); .................
声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
- 上一篇:没有了
- 下一篇:没有了