开发者社区> 问答> 正文

如何在Android上的JNI下捕获SIGSEGV(分段错误)并获取堆栈跟踪?

我正在将一个项目移至新的Android Native Development Kit(即JNI),并且我想抓住SIGSEGV(如果它发生的话(可能还有SIGILL,SIGABRT,SIGFPE)),以便呈现一个不错的崩溃报告对话框,而不是(或之前)当前发生的情况:该进程立即异常终止,并且操作系统可能会尝试重新启动该进程。(编辑: JVM / Dalvik VM捕获信号并记录堆栈跟踪和其他有用的信息;我只想向用户提供将这些信息通过电子邮件发送给我的选项。)

情况是:我没有编写大量的C代码,完成了该应用程序(所有游戏逻辑)的大部分工作,尽管它在许多其他平台上都经过了良好的测试,但我在Android中完全有可能端口,将其作为垃圾进行处理,并导致本机代码崩溃,因此我希望当前显示在Android日志中的崩溃转储(本机和Java)(我猜这在非Android情况下将是stderr)。我可以随意修改C和Java代码,尽管回调(进入和退出JNI)的数量大约为40,显然,小差异的加分。

我听说过J2SE中的信号链库libjsig.so,如果我可以在Android上安全地安装类似的信号处理程序,那将解决我的问题中最棘手的部分,但是我没有看到这样的Android / Dalvik库。

展开
收起
Puppet 2020-01-20 11:21:26 822 0
1 条回答
写回答
取消 提交回答
  • 编辑:从Jelly Bean开始,您无法获取堆栈跟踪,因为READ_LOGS走了。:-(

    我实际上让信号处理程序工作了,而没有做任何多余的事情,并且已经发布了使用它的代码,您可以在github上看到它(编辑:链接到历史版本;从那时起我删除了崩溃处理程序)。就是这样:

    使用sigaction()捕捉到信号并存储旧的处理程序。(android.c:570) 时间流逝,发生段错误。 在信号处理程序中,最后一次调用JNI,然后调用旧的处理程序。(android.c:528) 在该JNI调用中,记录所有有用的调试信息,然后调用startActivity()标记为需要在其自己的进程中进行的活动。(SGTPuzzles.java:962,AndroidManifest.xml中:28) 当您从Java回来并调用该旧处理程序时,Android框架将连接到debuggerd为您记录一个不错的本机跟踪,然后该过程将终止。(debugger.c,debuggerd.c) 同时,您的崩溃处理活动正在启动。确实,您应该将PID传递给它,以便它可以等待第5步完成;我不这样做 在这里,您向用户表示歉意,并询问是否可以发送日志。如果是这样,则收集的输出logcat -d -v threadtime并启动ACTION_SEND收件人,主题和正文已填写的用户。用户将必须按Send。(CrashHandler.java,SGTPuzzles.java : 462,strings.xml:41 当心logcat失败或花费超过几秒钟的时间。我遇到了一种设备,T-Mobile Pulse / Huawei U8220,logcat立即进入T(跟踪)状态并挂起。(CrashHandler.java:70,strings.xml中:51) 在非Android情况下,其中一些可能会有所不同。您需要收集自己的本机跟踪,请参见另一个问题,具体取决于您拥有的是哪种libc。您需要处理该跟踪的转储,启动单独的崩溃处理程序流程,并以适合您平台的某些方式发送电子邮件,但是我认为一般方法仍然可以使用。

    2020-01-23 12:47:39
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
58同城Android客户端Walle框架演进与实践之路 立即下载
Android组件化实现 立即下载
蚂蚁聚宝Android秒级编译——Freeline 立即下载