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

[Crash Log]

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x98  
  2. Stack frame D/CrashAnrDetector(  859):     #00 pc 000b16f4  /system/lib/libart.s  
  3. o (art::JniAbort(char const*, char const*)+47)  
  4. Stack frame D/CrashAnrDetector(  859):     #01 pc 000b2045  /system/lib/libart.s  
  5. o (art::JniAbortF(char const*, char const*, ...)+60)  
  6. Stack frame D/CrashAnrDetector(  859):     #02 pc 000b4d9f  /system/lib/libart.s  
  7. o (art::ScopedCheck::ScopedCheck(_JNIEnv*, int, char const*)+334)  
  8. <span style="color:#FF0000;">Stack frame D/CrashAnrDetector(  859):     #03 pc 000b5e35  /system/lib/libart.s  
  9. o (art::CheckJNI::FindClass(_JNIEnv*, char const*)+20)</span>  
  10. <span style="color:#FF0000;">Stack frame D/CrashAnrDetector(  859):     #04 pc 0003f554  /data/app/com.nation  
  11. sky.rc.samsung-1/lib/arm/librc.so: Routine _JNIEnv::FindClass(char const*) at D:</span>  
  12. /dev/android-ndk-r10e/platforms/android-21/arch-arm/usr/include/jni.h:519  
  13. Stack frame D/CrashAnrDetector(  859):     #05 pc 0007c174  /data/app/com.nation  
  14. sky.rc.samsung-1/lib/arm/librc.so: Routine event_handler at E:\MDM\RemoteControl  
  15. l-sansang2\RemoteControll-sansang/jni/remotecontroll/remotecontroll.cpp:35625  
  16. Stack frame D/CrashAnrDetector(  859):     #06 pc 000662b8  /data/app/com.nation  
  17. sky.rc.samsung-1/lib/arm/librc.so: Routine call_user at E:\MDM\RemoteControll-sa  


[Crash原因分析]

出错的代码:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 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 ? 在CODE上查看代码片 派生到我的代码片
  1. JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, __null };  
  2. JNIEnv* jniEvn = __null;  
  3. int res = javaVm->AttachCurrentThread(&jniEvn, &args);  
  4.        jclass tmp = jniEvn->FindClass("com/xxx/xx/xx/xxxxx");  

2.但这么做仍然后crash,是说4.0上回收机制有改变,需要使用NewGlobalRef()生成全局变量才能用
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. remotedesktopclass = (jclass)jniEnv->NewGlobalRef(tmp);  

 

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

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 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>  
  2. Line 2151: F/art     ( 1223): sart/runtime/check_jni.cc:65]     in call to NewGlobalRef  
  3. Line 2153: F/art     ( 1223): sart/runtime/check_jni.cc:65] "keyPress" prio=5 tid=14 Runnable  
  4. Line 2155: F/art     ( 1223): sart/runtime/check_jni.cc:65]   | group="main" sCount=0 dsCount=0 obj=0x12ccb080 self=0xb7c98350  
  5. 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  
  6. 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 ? 在CODE上查看代码片 派生到我的代码片
  1. JNIEXPORT void JNICALL Java_xx_xx_xx_xx_xxx(JNIEnv * jniEnv, jobject object, jstring jflowNum, jstring judid){  
  2.      jniEnv->GetJavaVM(&javaVm);  
  3.      jclass tmp = jniEnv->FindClass("com/nationsky/rc/util/RemoteDesktopUtil");  
  4.      remotedesktopclass = (jclass)jniEnv->NewGlobalRef(tmp);  
  5.      .............  
修改地方2:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. static void keyPress(int keyCode){  
  2.     JavaVMAttachArgs args = { JNI_VERSION_1_6, __FUNCTION__, __null };  
  3.     JNIEnv* jniEvn = __null;  
  4.     int res = javaVm->AttachCurrentThread(&jniEvn, &args);  
  5.         method = jniEvn->GetStaticMethodID(remotedesktopclass,  
  6.                                "pressHome""()V");  
  7.         .................  
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值