您的位置:首页 > 其它

使用JNIEnv全局变量调用FindClass()等函数发生crash

2017-03-22 11:24 1366 查看
[Crash Log]

[html] view
plain copy

 print?





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:\MDM\RemoteControl  

l-sansang2\RemoteControll-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:\MDM\RemoteControll-sa  

[Crash原因分析]

出错的代码:

[cpp] view
plain copy

 print?





jclass remotedesktopclass = sJniEnv->FindClass("com/xxx/xxx/xxx/xxx");  

sJniEnv是一个全局变量,但其实不应该全局保存JNIEnv。

这是一个和thread紧密关联的变量,在其他线程中使用就会crash。

【参考】

http://blog.csdn.net/freechao/article/details/7692239




【解决方式】

1.参考了第一篇文章,保存一个JavaVM全局变量,然后再其他线程中使用AttachCurrentThread(),代码如下:

[cpp] view
plain copy

 print?





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()生成全局变量才能用

[cpp] view
plain copy

 print?





remotedesktopclass = (jclass)jniEnv->NewGlobalRef(tmp);  



3.上面两部修改后其实还是不行,Log如下:

[cpp] view
plain copy

 print?





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:

[cpp] view
plain copy

 print?





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:

[cpp] view
plain copy

 print?





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");  

        .................  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐