使用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");
.................
[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");
.................
相关文章推荐
- 使用JNIEnv全局变量调用FindClass()等函数发生crash
- 递归调用中使用全局变量或者函数参数
- [初学笔记]matlab中主函数和次函数的建立和调用(嵌套与不嵌套),全局变量global与子函数的使用
- c语言中头文件的建立与使用-函数、全局变量、全局数组
- VC6.0下调用Dll文件提供的函数接口和全局变量(转)
- Php 中全局变量在函数中使用时必须申明为全局
- js中的全局变量和静态变量的使用, js 的调试?- 如果js出错, js引擎 就会停止, 这会 导致 后面的 html中 refer 该函数时, 会报错 函数为定义!!
- matlab全局变量(global):够被其他函数调用.在这两个函数中都要用global修饰这个变量.
- 自定义函数内可以使用全局变量吗?答案是不可以,需要关键字global
- jquery ajax success 函数 异步调用方法中不能给全局变量赋值的原因及解决办法
- Ajax - 在函数中使用Ajax怎么使用返回值 - Ajax赋值给全局变量异常的解决方法
- 在C++工程中main函数之前跑代码的廉价方法(使用全局变量和全局函数)
- 在Angular外部使用js调用Angular控制器中提供的函数方法或变量
- 一个函数调用另一个函数,最好用参数传递。不然就得声明为全局变量。被调用的函数里边,变量前面写 global
- C++类里的成员函数如何调用全局变量
- j解决sparkr中使用某些r的原生函数 发生错误Error: class(objId) == "jobj" is not TRUE的问题
- python函数中使用全局变量
- python 在函数中使用全局变量的注意事项
- 关于全局变量和函数,在其他类中调用问题,extern关键字
- 利用VS2010生成DLL文件及DLL中函数和全局变量的使用