2012-04-27 108 views
1

这是与NDK和Android SDK的问题。 目前,我的C代码正在调用Java中定义的方法。这个方法叫做callFromNDK()。JNI - 应用程序崩溃

在这个方法中,我引用了媒体播放器的实例,以发挥短的测试音。 callFromNDK()每2秒调用一次。测试音本身是一秒钟。

我看到的是一个 (SIGSEGV),代码1(SEGV_MAPERR),有时还有故障地址fffffff4。

我想知道如果发生这种情况,因为媒体播放器的实例是在不同的上下文,它在渐渐习惯了一个创造出来的?

下面是相关的代码段[爪哇文件]

public class Canvastutorial extends Activity { 
    private static MediaPlayer mediaPlayer = null; 
    public void callFromNDK() { 
     if (mediaPlayer != null) { 
      mediaPlayer.start(); 
     } 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.audioclip); 
     mediaPlayer.setLooping(false); 
    } 

    @Override 
    protected void onDestroy() { 
     mediaPlayer.release(); 
     mediaPlayer = null; 
     System.gc(); 
     super.onDestroy(); 
    } 

    @Override 
    protected void onPause() { 
     stopAndPrepare(); 
     super.onPause(); 
    } 

    private void stopAndPrepare() { 
      mediaPlayer.stop(); 
      try { 
       mediaPlayer.prepare(); 
      } catch (IllegalStateException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      mediaPlayer.seekTo(0); 
    } 
} 

的logcat的是如以下时应用程序崩溃:

04-27 10:42:13.228: I/DEBUG(8926): Build fingerprint: 'google/passion/passion:2.3.6/GRK39F/189904:user/release-keys' 
04-27 10:42:13.228: I/DEBUG(8926): pid: 10362, tid: 11222 >>> <package_name> <<< 
04-27 10:42:13.228: I/DEBUG(8926): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr fffffff4 
04-27 10:42:13.238: I/DEBUG(8926): r0 4214cdc0 r1 00000000 r2 00000000 r3 0000ce68 
04-27 10:42:13.238: I/DEBUG(8926): r4 44628398 r5 00000000 r6 4472fbd8 r7 0000000e 
04-27 10:42:13.238: I/DEBUG(8926): r8 80018000 r9 00000000 10 00000000 fp 800a5368 
04-27 10:42:13.238: I/DEBUG(8926): ip 00000000 sp 4472fb88 lr 8001d084 pc 8001d090 cpsr 60000010 
04-27 10:42:13.238: I/DEBUG(8926): d0 00650072006800b8 d1 00000044bed7f457 
04-27 10:42:13.238: I/DEBUG(8926): d2 0069006400650052 d3 004d0049002e0040 
04-27 10:42:13.238: I/DEBUG(8926): d4 0061006900640065 d5 00790061006c0050 
04-27 10:42:13.238: I/DEBUG(8926): d6 0065005300720065 d7 0063006900760072 
04-27 10:42:13.238: I/DEBUG(8926): d8 0000000000000000 d9 0000000042ba56de 
04-27 10:42:13.238: I/DEBUG(8926): d10 0000000000000000 d11 0000000000000000 
04-27 10:42:13.238: I/DEBUG(8926): d12 0000000000000000 d13 0000000000000000 
04-27 10:42:13.238: I/DEBUG(8926): d14 0000000000000000 d15 0000000000000000 
04-27 10:42:13.238: I/DEBUG(8926): d16 0000000000000001 d17 c053000000000000 
04-27 10:42:13.238: I/DEBUG(8926): d18 0000000000000000 d19 0000000000000000 
04-27 10:42:13.238: I/DEBUG(8926): d20 3ff0000000000000 d21 8000000000000000 
04-27 10:42:13.238: I/DEBUG(8926): d22 0000000000000000 d23 ff00000000000000 
04-27 10:42:13.238: I/DEBUG(8926): d24 ff00000000000000 d25 ff00000000000000 
04-27 10:42:13.238: I/DEBUG(8926): d26 0100010001000100 d27 0100010001000100 
04-27 10:42:13.238: I/DEBUG(8926): d28 0100010001000100 d29 3ff0000000000000 
04-27 10:42:13.238: I/DEBUG(8926): d30 0000000000000000 d31 3ff0000000000000 
04-27 10:42:13.238: I/DEBUG(8926): scr 60000012 
04-27 10:42:13.328: I/DEBUG(8926):   #00 pc 0001d090 /system/lib/libdvm.so 
04-27 10:42:13.328: I/DEBUG(8926):   #01 pc 000220e4 /system/lib/libdvm.so 
04-27 10:42:13.328: I/DEBUG(8926):   #02 pc 00020fdc /system/lib/libdvm.so 
04-27 10:42:13.328: I/DEBUG(8926):   #03 pc 0005fc40 /system/lib/libdvm.so 
04-27 10:42:13.328: I/DEBUG(8926):   #04 pc 0004cff8 /system/lib/libdvm.so 
04-27 10:42:13.328: I/DEBUG(8926):   #05 pc 00001590 /data/data/<package_name>/lib/libtest-jni.so 
04-27 10:42:13.328: I/DEBUG(8926):   #06 pc 000016ca /data/data/<package_name>/lib/libtest-jni.so 
04-27 10:42:13.328: I/DEBUG(8926):   #07 pc 000118e4 /system/lib/libc.so 
04-27 10:42:13.328: I/DEBUG(8926):   #08 pc 000114b0 /system/lib/libc.so 
04-27 10:42:13.328: I/DEBUG(8926): code around pc: 
04-27 10:42:13.328: I/DEBUG(8926): 8001d070 fa0108cc ea000017 e3a00001 e3a09000 
04-27 10:42:13.328: I/DEBUG(8926): 8001d080 ebffff72 e2450014 e5905000 e5909004 
04-27 10:42:13.328: I/DEBUG(8926): 8001d090 e515200c e5963018 e3520000 1592a000 
04-27 10:42:13.328: I/DEBUG(8926): 8001d0a0 e3a01000 0affff8a e1f970b6 e5862010 
04-27 10:42:13.328: I/DEBUG(8926): 8001d0b0 e59a1028 e5835028 e590a010 e1a04009 
04-27 10:42:13.328: I/DEBUG(8926): code around lr: 
04-27 10:42:13.328: I/DEBUG(8926): 8001d064 e088f30c e1a01000 e5960018 fa0108cc 
04-27 10:42:13.328: I/DEBUG(8926): 8001d074 ea000017 e3a00001 e3a09000 ebffff72 
04-27 10:42:13.328: I/DEBUG(8926): 8001d084 e2450014 e5905000 e5909004 e515200c 
04-27 10:42:13.328: I/DEBUG(8926): 8001d094 e5963018 e3520000 1592a000 e3a01000 
04-27 10:42:13.328: I/DEBUG(8926): 8001d0a4 0affff8a e1f970b6 e5862010 e59a1028 
04-27 10:42:13.328: I/DEBUG(8926): stack: 
04-27 10:42:13.328: I/DEBUG(8926):  4472fb48 4472fbe0 
04-27 10:42:13.328: I/DEBUG(8926):  4472fb4c 4214cce4 
04-27 10:42:13.328: I/DEBUG(8926):  4472fb50 0000ce60 
04-27 10:42:13.328: I/DEBUG(8926):  4472fb54 00000001 
04-27 10:42:13.328: I/DEBUG(8926):  4472fb58 4472fbe0 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb5c 80049697 /system/lib/libdvm.so 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb60 4214cce4 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb64 431fbec9 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb68 ad34675d /system/lib/libandroid_runtime.so 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb6c 4472fbe0 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb70 42f8e91e 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb74 4214cd00 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb78 4472fbd8 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb7c 40038360 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb80 df002777 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb84 e3a070ad 
04-27 10:42:13.338: I/DEBUG(8926): #00 4472fb88 4214e32c 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb8c 4472fbd8 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb90 00000001 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb94 002c2c40 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb98 0000ce68 
04-27 10:42:13.338: I/DEBUG(8926):  4472fb9c 000f45b8 
04-27 10:42:13.338: I/DEBUG(8926):  4472fba0 800aad38 
04-27 10:42:13.338: I/DEBUG(8926):  4472fba4 fffffe84 
04-27 10:42:13.338: I/DEBUG(8926):  4472fba8 800a5368 
04-27 10:42:13.338: I/DEBUG(8926):  4472fbac 800220e8 /system/lib/libdvm.so 
04-27 10:42:13.338: I/DEBUG(8926): #01 4472fbb0 4472fbd8 
04-27 10:42:13.338: I/DEBUG(8926):  4472fbb4 0000ce60 
04-27 10:42:13.338: I/DEBUG(8926):  4472fbb8 80022058 /system/lib/libdvm.so 
04-27 10:42:13.338: I/DEBUG(8926):  4472fbbc 423298c8 
04-27 10:42:13.338: I/DEBUG(8926):  4472fbc0 00000000 
04-27 10:42:13.338: I/DEBUG(8926):  4472fbc4 80020fe0 /system/lib/libdvm.so 

任何想法是表示赞赏。

谢谢。

该项目的本机端:在thread_function获取的所谓的周期性(2秒间隔)而这也正是我打电话Java代码中定义的函数。

// Callbacks to Android 
JavaVM *j_vm; 
jobject *j_obj; 
JNIEnv *j_env; 
jclass j_cls; 
jmethodID android_call; 

int JNI_OnLoad(JavaVM* vm, void* reserved) { 
    j_vm = vm; 
    (*j_vm)->GetEnv(j_vm, (void**) &j_env, JNI_VERSION_1_6); 
    j_cls = (*j_env)->FindClass(j_env, "<package_name>/<class_name>"); 
    android_call = (*j_env)->GetMethodID(j_env, j_cls, "callFromNDK", "()V"); 
    j_obj = (*j_env)->NewGlobalRef(j_env, (*j_env)->NewObject(j_env, j_cls, android_call)); 
    return JNI_VERSION_1_6; 
} 

void JNI_OnUnload(JavaVM *vm, void *reserved) { 
    (*j_env)->DeleteGlobalRef(j_env, j_obj); 
} 

void *thread_function(void *ptr) { 
    int *which = (int *) ptr; 
    (*j_vm)->AttachCurrentThread(j_vm, &j_env, NULL); 
    int rc; 
    while (!stop_thread) { 
     rc = pthread_mutex_lock(&mtx); 
     rc = pthread_cond_wait(&cond, &mtx); 
     rc = pthread_mutex_unlock(&mtx); 
     if (!stop_thread) { 
      (*j_env)->CallVoidMethod(j_env, j_obj, android_call); 
     } 
    } 
    (*j_vm)->DetachCurrentThread(j_vm); 
    return NULL; 
} 
+0

什么是调用thread_function?不管它的具体问题,我想你可以添加周围的mediaPlayer.start()的一些记录和异常处理 - 也已经在这一点上编制的,对不对?值得重新阅读的mediaplyer文档。 – 2012-04-27 18:33:35

+0

thread_function是在创建线程时注册的函数指针。这是线程开始运行时调用的函数。是的,mediaPlayer实例被创建并且非空。该应用程序运行约15或20分钟,然后崩溃。应用程序崩溃花费的时间长度不确定。对mediaPlayer.start()进行调试日志并没有帮助,因为这不是问题所在。正如@StarDust指出的那样,问题必须出现在我的本地代码中。你可以给我一些关于如何调试本地代码而不是放置日志语句的指导吗?谢谢。 – 2012-04-27 23:55:36

+1

问题可能是在你的代码,但转储表明实际崩溃发生在libdvm.so代替。因此,您需要弄清楚您的代码可能会将DVM设置为崩溃。在崩溃之前执行的代码最后一行记录事件状态可能会有所帮助,特别是在对mediaPlayer对象错误使用的情况下。为了更好地识别代码中的最后一点,可以使用地址来指定工具或objdump来识别堆栈转储中提到的libtest-jni.so中的两个点。你也可以设置GDB ... – 2012-04-28 00:02:47

回答

0

您是否试过在模拟器中运行它?由于它在libdvm中崩溃,您可能会在本机崩溃之前获得一些非常有用的日志记录。

的问题可能是以下行:

j_cls = (*j_env)->FindClass(j_env, "<package_name>/<class_name>"); 

它是安全的假设你的实际命名空间和类名替换"<package_name>/<class_name>"

+0

是的。假设package_name和class_name的详细信息是正确的并且它们完全合格,这是安全的。我没有尝试模拟器,因为程序需要音频输入才能工作。但这是一个很好的建议。我会尝试隔离音频输入部分,并使用模拟器,看看会发生什么。谢谢。 – 2012-05-01 01:52:49

0

由于我在这段代码中看到了三个错误,但是运行CheckJNI(http://android-developers.blogspot.com/2011/07/debugging-android-jni-with-checkjni.html)和Dalvik应该告诉你你做错了什么。 (你应该运行最新的版本以获得最佳检查结果,我注意到的一个错误不会被姜饼发现[并且你也会在姜饼中得到它)。)

你应该总是使用CheckJNI,同时开发和调试。在发布任何包含单词JNI的问题之前,StackOverflow应该可能让人们检查“是的,我试过CheckJNI”框:

+0

不知道CheckJNI - 新手JNI用户在这里。我会通过CheckJNI查看是否所有代码都正确。 thx为小费。 – 2012-05-01 01:54:03