我正在开发一个新的Java桌面应用程序,并希望包含一个崩溃报告工具 - 你知道那种事情 - 程序崩溃,弹出框要求用户点击好发送它等等。
我很清楚如何将错误发送回我们的服务器 - 可能是通过一个简单的Web服务。我更不确定的是如何实现捕获故障的机制?我会欢迎任何已经实施过类似建议的人的建议。
答案 0 :(得分:7)
有一个命令行选项可以让JVM在JVM与内存转储崩溃后运行批处理文件。您所要做的就是创建一个执行错误报告的外部程序,然后使用JVM选项使用您创建的实用程序在电子邮件中发送核心转储。
-XX:-HeapDumpOnOutOfMemoryError -XX:OnError="<cmd args>;<cmd args>"
答案 1 :(得分:5)
使用Thread.setUncaughtExceptionHandler和静态Thread.setDefaultUncaughtExceptionHandler来(尝试)向您的日志记录系统报告异常。
答案 2 :(得分:2)
我看到三个案例:
灾难。 JVM本身要么死了,要么死了。您不能假设您的任何代码都能够工作 - 例如,您无法分配任何内存。因此,在这种情况下,您无法合理地希望能够发送任何诊断信息。您可以期待的最好的方法是在死亡程序的灰烬中留下一些诊断信息,例如核心转储。
在这种情况下,您可以在启动新运行时查找此类碎片并建议用户收集它,或者更多的努力尝试自己组装诊断包。
低级应用程序代码不会捕获异常,可能是RunTime异常,例如NullPointer异常。在这种情况下,你可以在你的主要(假设你有一个)你可以捕获异常,并希望你的Crash Reporter代码可以工作。 将异常及其堆栈跟踪传递给Crash Reporter。
你的低级代码捕捉到了一些非常不健康的东西。不足以终止流程,但值得报告。在这里,您不仅可以获得例外,还可以获得其他上下文信息。我们还有更多要发送给Crash Reporter。
答案 3 :(得分:2)
使用日志记录。通用模式的工作方式如下:
ERROR
答案 4 :(得分:0)
我不知道这是否是Java目前提供的最佳功能,但这是我一段时间所做的。
首先,所有可能崩溃的有趣活动都是通过命令模式发送的。这个应用程序包括通过互联网访问应用程序服务器,所以很多可能会出错。命令调度程序捕获了异常并向用户显示了相应的结果(通常显示错误对话框,然后是关闭和发送有关崩溃的电子邮件)。
其次,在Swing中使用自定义事件队列来捕获事件线程上发生的任何异常。我希望Java现在有更好的解决方案,但基本上当发生异常时你必须检查你的代码是否涉及,否则一些Swing错误可能会使你的应用程序崩溃,这是不愉快的。当然,必须检查递归(当您尝试向用户显示消息时,崩溃会一遍又一遍地重复)。
顺便说一下,大多数崩溃都会让你的JVM继续运行,包括内存不足错误,足以在大多数情况下发送电子邮件,因为内存不足错误后错误通常会释放出足够的堆栈(和因此堆)允许进一步的垃圾收集并让您的代码生效。但在这种情况下你仍然应该迅速退出。 IDEA在出现内存不足错误后继续运行,但通常运行不正常。他们最好离开,IMO。
使用以下和子类EventQueue推送新队列以链接您的行为。
Toolkit.getDefaultToolkit().getSystemEventQueue().push(newQueue);
答案 5 :(得分:0)
一种选择是使用BugSense。它针对移动应用程序崩溃报告,但API声明它可用于任何类型的崩溃报告。从我读过的内容中可以很简单,所有需要做的就是创建一个包含所有值的简单POST请求。
{
"client": {
"name": "bugsense-android", // Obligatory
"version": "0.6"
},
"request": {
"remote_ip": "10.0.0.1",
"custom_data": {
"key1": "value1",
"key2": "value2"
}
},
"exception": {
"message": "java.lang.RuntimeException: exception requested", // Obligatory
"where": "MainActivity.java:47", // Obligatory
"klass": "java.lang.RuntimeException", // Type of exception
"backtrace": "java.lang.RuntimeException: exception requested\r\nat com.sfalma.trace.example.MainActivity$1.onClick(MainActivity.java:47)\r\nat android.view.View.performClick(View.java:2408)\r\nat android.view.View$PerformClick.run(View.java:8816)\r\nat android.os.Handler.handleCallback(Handler.java:587)\r\nat android.os.Handler.dispatchMessage(Handler.java:92)\r\nat android.os.Looper.loop(Looper.java:123)\r\nat android.app.ActivityThread.main(ActivityThread.java:4627)\r\nat java.lang.reflect.Method.invokeNative(Native Method)\r\nat java.lang.reflect.Method.invoke(Method.java:521)\r\nat com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)\r\nat com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)\r\nat dalvik.system.NativeStart.main(Native Method)\\n" // Obligatory
},
"application_environment": {
"phone": "android", // Device model (could be PC or Max) Obligatory
"appver": "1.2", // Obligatory
"appname": "com.sfalma", // Obligatory
"osver": "2.3", // Obligatory
"wifi_on": "true",
"mobile_net_on": "true",
"gps_on": "true",
"screen_dpi(x:y)": "120.0:120.0",
"screen:width": "240",
"screen:height": "400",
"screen:orientation": "normal"
}
}