【问题标题】:Strategies/techniques for crash reporting in JavaJava 中的崩溃报告策略/技术
【发布时间】:2009-08-21 16:03:55
【问题描述】:

我正在开发一个新的 Java 桌面应用程序,并希望包含一个崩溃报告工具 - 你知道那种事情 - 程序崩溃、弹出框要求用户单击确定以发送它等等。

我对如何将错误发送回我们的服务器感到满意——可能是通过一个简单的网络服务。我更不确定的是应该如何实现捕获故障的机制?我欢迎任何实施过类似功能的人提供任何建议。

【问题讨论】:

  • 还发现了一种跟踪 JVM 的好方法:使用名为 Java-Monitor.com 的东西。它不是免费的,但代码足够公开,您可能能够实现类似的东西。

标签: java error-handling crash


【解决方案1】:

您可以为 JVM 提供一个命令行选项,该选项将在 JVM 因内存转储而崩溃后运行批处理文件。您所要做的就是创建一个执行错误报告的外部程序,然后使用 JVM 选项使用您创建的实用程序通过电子邮件发送核心转储。

-XX:-HeapDumpOnOutOfMemoryError -XX:OnError="<cmd args>;<cmd args>"

【讨论】:

  • 当然,您还希望将此方法与运行时错误报告功能结合起来......
【解决方案2】:

使用 Thread.setUncaughtExceptionHandler 和静态 Thread.setDefaultUncaughtExceptionHandler 来(尝试)向您的日志记录系统报告异常。

【讨论】:

    【解决方案3】:

    我看到三种情况:

    1. 灾难。 JVM 本身要么死了,要么死了。你不能假设你的任何代码都能够工作——例如你不能分配任何内存。因此,在这种情况下,您无法合理地希望能够发送任何诊断信息。您可以期望的最好结果是进行一些诊断,例如将核心转储留在死程序的灰烬中。

      在这种情况下,您可以在启动新运行时查找此类碎片并建议用户收集它,或者尝试自己组装诊断包。

    2. 低级应用程序代码不会捕获异常,可能是运行时异常,例如 NullPointer 异常。在这种情况下,您可以在您的主要(假设您有一个)中捕获异常并希望您的 Crash Reporter 代码能够正常工作。 将异常及其堆栈跟踪传递给 Crash Reporter。

    3. 你的低级代码捕获了一些非常不健康的东西。不足以终止进程,但值得报告。在这里,您不仅可以获得例外情况,还可以获得其他上下文信息。我们还有更多内容要发送给 Crash Reporter。

    【讨论】:

    • 桌面应用程序实际上没有 main 方法。主线程在显示框架时结束(以及在方法完成之前它所做的任何其他事情)。
    • 在大多数情况下是的,这就是为什么我说“如果你有的话”,但是有一些非 ui 桌面应用程序可以有一个 main.无论如何,最好知道在没有 main 的情况下你会推荐什么。
    【解决方案4】:

    使用日志记录。通用模式的工作方式如下:

    • 创建一个将错误消息发送到服务器的附加程序(大多数日志框架支持通过邮件甚至 JDBC 传输日志消息的附加程序)。如果没有现有的附加程序,他们有示例如何做到这一点。
    • 将该附加程序添加到根记录器并将其阈值设置为ERROR
    • 发现异常时记录错误。然后,日志框架将为您完成相关工作。

    【讨论】:

      【解决方案5】:

      我不知道这是否是 Java 目前所能提供的最好的,但这是我不久前所做的。

      首先,所有可能崩溃的有趣活动都是通过命令模式分派的。该应用程序包括通过 Internet 访问应用程序服务器,因此可能会出现很多问题。命令调度程序捕获了异常并将相应的结果显示给用户(通常显示一个错误对话框,然后是关机和发送有关崩溃的电子邮件)。

      其次,在 Swing 中使用了一个自定义事件队列来捕获事件线程上发生的任何异常。我希望 Java 现在有更好的解决方案,但基本上当发生异常时,您必须检查您的代码是否涉及,否则一些 Swing 错误可能会使您的应用程序崩溃,这并不令人愉快。当然,必须检查递归(当您尝试向用户显示消息时,崩溃会一遍又一遍地重复)。

      顺便说一句,大多数崩溃都会让你的 JVM 继续运行,包括内存不足错误,在大多数情况下足以发送电子邮件,因为在内存不足错误之后,通常错误会释放足够多的堆栈(以及因此堆)以允许进一步的垃圾收集并让您的代码生效。但在这种情况下,您仍然应该快速退出。 IDEA 会继续处理内存不足错误,但通常无法正常运行。他们最好退出,IMO。

      您推送一个带有以下子类的新队列 EventQueue 以链接您的行为。

       Toolkit.getDefaultToolkit().getSystemEventQueue().push(newQueue);
      

      【讨论】:

        【解决方案6】:

        一种选择是使用 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"
           }
        }
        

        你可以read more about it here

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-27
          • 2010-11-24
          • 1970-01-01
          • 2023-04-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多