【问题标题】:Have program recognize it crashed last time?程序是否识别它上次崩溃?
【发布时间】:2009-11-17 13:13:47
【问题描述】:

让 (Java) 程序在上次运行时识别出它崩溃并显示一条类似“看起来这个程序上次在你身上崩溃的消息”的最佳方法是什么。在此处报告此问题:bla@foo .com ....”

有推荐的方法吗? (坏的?)我的想法是:

  • 让程序在启动时存储一个临时密钥文件,然后在定期关闭时将其删除。如果文件在启动时存在,则显示消息。
  • 在这种情况下识别死锁并存储“错误文件”。如果启动时存在“错误文件”,请显示错误消息并将文件移动到存档或类似文件中。

【问题讨论】:

    标签: java error-handling crash-reports


    【解决方案1】:

    Java 程序崩溃的三个原因:

    • 未处理的运行时异常。使用main 中的try-catch 很容易解决这个问题。
    • 未处理的错误。这些很少见,但也可以在main 中找到。我通常在main 中捕获Throwable。请参阅下面的模板。
    • 如果您使用线程,请查看Thread.setDefaultUncaughtExceptionHandler()
    • VM 中的错误,或程序被用户杀死,或硬件暴力关闭。这些将导致无法捕获的崩溃。在这里,您最好的选择是使用new File(...).deleteOnExit() 在某处创建一个标志文件。如果有机会,Java 会为您清理它。

    死锁的问题是如何检测你有死锁。我还没有看到一种一致的方法来做到这一点。

    import org.apache.commons.lang.exception.ExceptionUtils;
    
    public class Demo
    {
        public static void main (String[] args)
        {
            try
            {
                Demo obj = new Demo ();
                obj.run (args);
                System.out.println ("Done.");
            }
            catch (Throwable t)
            {
                ExceptionUtils.printRootCauseStackTrace (t);
            }
        }
    }
    

    【讨论】:

    • 或者程序被用户杀死,或者硬件暴力关机等
    • 这只捕获了“主”线程的问题。如果您启动额外的线程,那么如果它们抛出运行时异常或错误,则消息将丢失。
    【解决方案2】:

    在未捕获的异常中崩溃?使用Thread.setDefaultUncaughtExceptionHandler,并将消息显示为崩溃的一部分。

    关于第一个想法,您如何处理同时运行的应用程序的多个实例? (还要考虑多用户环境)。

    识别死锁 - 死锁多久出现一次问题?我猜你可以监控所有“关键”线程上的thread states

    然后你有外部力量杀死应用程序,它们是否应该被认为是你应该报告的问题?毕竟,在这种情况下,您的应用程序没有错。

    最后,始终以日志的形式存储“错误文件”。使用适当的日志框架(即Java LoggingLog4J)。您可以检查最后几行以获取应用程序正常退出的信号,但在多实例环境中您需要小心。

    【讨论】:

      【解决方案3】:

      您提出的第一个解决方案的变体在 Un*x 上对于进程来说很常见:在启动时将正在运行的进程的 pid 文件存储在一个文件中。当程序再次启动时,您可以检查此文件是否仍然存在(即使具有此 pid 的进程正在运行)。

      使用 Java,您可能可以使用 ThreadMXBean 中定义的 Threadid 来适应这个想法。但是任何文件都可以。包含您建议的密钥的文件似乎是一种足够好的方法。您还可以在其中放入一些有用的信息,例如上次执行时间。如果它在启动时仍然存在,则程序没有完全停止。

      它也可以变成类似启动日志文件的东西,用于跟踪程序事件,包括启动和干净停止,可能还有锁定。

      【讨论】:

        【解决方案4】:

        我所做的是将 System.err 重定向到一个文件,以便任何错误消息(如崩溃)最终出现在一个我可以稍后处理的文件中......

        执行此操作的代码非常简单...

        String errLog = "c:\\myLog";
        try 
        {
          java.io.PrintStream err = new java.io.PrintStream(new java.io.FileOutputStream(errLog));
          System.setErr(err);
        }
        catch (java.io.FileNotFoundException fnfe) {}
        

        【讨论】:

        • 我建议使用适当的日志框架而不是重定向 System.err。
        【解决方案5】:

        我将在这里模仿马科斯。创建一个配置或日志文件,该文件将承载程序的最后一条错误消息和最后运行日期。然后在程序加载期间读取该文件。

        【讨论】:

          【解决方案6】:

          其中许多答案都是关于跟踪导致您的应用停止工作的异常。

          另一种可能性是应用程序刚刚退出(即用户将其关闭、计算机关闭、断电等)。我认为你的临时关键想法会为此工作。它类似于文本编辑程序(如 vi 或 Word)如何自动创建正在编辑的文件的特殊副本。打开时会检查特殊副本是否存在并询问您是否要恢复文件。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-03-10
            • 2014-01-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-03-18
            相关资源
            最近更新 更多