我正在移动a project到新的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上安装这样的信号处理程序,这将解决我的问题中的捕获部分,但我看不到这样的库机器人/的Dalvik。
答案 0 :(得分:79)
编辑:从Jelly Bean开始,您无法获得堆栈跟踪,因为READ_LOGS
went away。 : - (
我实际上有一个信号处理程序在没有做任何异国情调的情况下工作,并且已经使用它发布了代码,你可以看到on github(编辑:链接到历史版本;从那时起我删除了崩溃处理程序)。方法如下:
sigaction()
捕获信号并存储旧处理程序。 (android.c:570)startActivity()
。 (SGTPuzzles.java:962,AndroidManifest.xml:28)debuggerd
为你记录一个漂亮的本机跟踪,然后该进程将会死亡。 (debugger.c,debuggerd.c)logcat -d -v threadtime
的输出并启动ACTION_SEND
,其中包含收件人,主题和正文。用户必须按发送。 (CrashHandler.java,SGTPuzzles.java:462,strings.xml:41 logcat
失败或超过几秒钟。我遇到过一个设备,T-Mobile Pulse /华为U8220,其中logcat立即进入T
(跟踪)状态并挂起。 (CrashHandler.java:70,strings.xml:51)在非Android情况下,其中一些情况会有所不同。您需要收集自己的本机跟踪,请参阅this other question,具体取决于您拥有的libc类型。您需要处理转储跟踪,启动单独的崩溃处理程序进程,以及以适当的方式为您的平台发送电子邮件,但我认为一般方法仍然有效。
答案 1 :(得分:14)
我有点晚了,但我有完全相同的需求,我已经开发了一个小型库来解决它,通过捕捉常见的崩溃(SEGV
,SIBGUS
等。 )在 JNI代码中,并通过常规java.lang.Error
例外替换它们。奖励,如果客户端在Android> = 4.1.1
上运行,则堆栈跟踪会嵌入崩溃的已解析 backtrace (包含完整本机堆栈跟踪的伪跟踪)。您将无法从恶性崩溃中恢复(例如,如果您损坏了分配器),但至少它应该允许您从大多数中恢复。 (请报告成功与失败,代码是全新的)
https://github.com/xroche/coffeecatch的更多信息 (代码是 BSD 2条款许可)
答案 2 :(得分:6)
FWIW,Google Breakpad在Android上正常运行。我做了移植工作,我们将它作为Firefox Mobile的一部分发布。它需要一些设置,因为它不会在客户端提供堆栈跟踪,但会向您发送原始堆栈内存并执行堆栈服务器端(因此您不必使用应用程序发送调试符号) )。
答案 3 :(得分:5)
在我有限的经验(非Android)中,JNI代码中的SIGSEGV通常会在控制返回到Java代码之前使JVM崩溃。我模糊地回忆起一些非Sun JVM,它可以让你捕获SIGSEGV,但AFAICR你不能指望能够这样做。
您可以尝试在C中捕获它们(请参阅sigaction(2)),尽管在SIGSEGV(或SIGFPE或SIGILL)处理程序之后您可以做很少的事情,因为进程的持续行为是正式未定义的。