Программа распознала, что она в последний раз разбилась? - PullRequest
6 голосов
/ 17 ноября 2009

Каков наилучший способ заставить (Java) -программу распознавать, что она аварийно завершилась в прошлый раз, и показывать сообщение в виде «похоже, что эта программа разбилась на вас в последний раз. Сообщите о проблеме здесь: bla @ foo .com .... "

Есть ли рекомендуемый способ сделать это? (Плохо?) Идеи, которые у меня были:

  • Попросите программу сохранить файл временного ключа при запуске и затем удалить его при регулярном закрытии. Если файл существует при запуске, покажите сообщение.
  • В этом случае распознайте тупики и сохраните «файл ошибок». Если при запуске существует «файл ошибок», отобразите сообщение об ошибке и переместите файл в архив или что-то подобное.

Ответы [ 6 ]

7 голосов
/ 17 ноября 2009

Существует три причины сбоя Java-программы:

  • Необработанное исключение RuntimeException. Это легко решить с помощью try-catch in main.
  • Необработанные ошибки. Они редки, но также могут быть пойманы в main. Я обычно ловлю Throwable в main. Ниже приведен шаблон.
  • Если вы используете темы, посмотрите на Thread.setDefaultUncaughtExceptionHandler().
  • Ошибки в ВМ, или программа, убитая пользователем, или аппаратное принудительное завершение работы. Это приведет к аварии, которая не может быть поймана. Здесь ваш лучший вариант - создать файл флага где-нибудь с new File(...).deleteOnExit(). Ява очистит его для вас, если у него будет шанс.

Проблема с тупиками заключается в том, как определить, что у вас есть тупик. Я еще не видел последовательного способа сделать это.

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);
        }
    }
}
3 голосов
/ 17 ноября 2009

Сбой как в неисследованном исключении? Используйте Thread.setDefaultUncaughtExceptionHandler и отобразите сообщение как часть сбоя.

По первой идее, как вы обрабатываете несколько экземпляров одновременно работающих приложений? (Также подумайте о многопользовательской среде).

Распознавание взаимоблокировок. Как часто возникают взаимоблокировки? Я полагаю, вы могли бы отслеживать состояния потоков во всех "ключевых" потоках.

Тогда у вас есть внешние силы, убивающие приложение, должны ли они рассматриваться как проблема, о которой вы должны сообщить? Ведь ваша заявка не была виновата в этом случае.

Наконец, всегда сохраняйте «файл ошибок» в виде журнала. Используйте правильную структуру ведения журналов (т. Е. Java Logging или Log4J ). Вы можете проверить последние строки этого на наличие сигнала о том, что приложение нормально завершилось, но опять же вам нужно быть осторожным в средах с несколькими экземплярами.

2 голосов
/ 17 ноября 2009

Вариант первого решения, которое вы предлагаете, достаточно распространен в Un * x для процессов: сохраните файл pid запущенного процесса в файле при запуске. При повторном запуске программы вы можете проверить, существует ли этот файл (и даже если процесс с этим pid запущен).

С Java вы могли бы адаптировать эту идею, используя Threadid, определенный в ThreadMXBean. Но любой файл подойдет. Файл, который содержит ключ, как вы предлагаете, кажется достаточно хорошим способом. Вы также можете поместить в него некоторую полезную информацию, такую ​​как время последнего выполнения. Если это все еще там при запуске, программа не остановилась чисто.

Он также может стать чем-то вроде файла журнала запуска, который отслеживает события программы, включая запуск и чистые остановки, и, возможно, блокировки.

0 голосов
/ 17 ноября 2009

Многие из этих ответов касаются отслеживания исключений, из-за которых ваше приложение перестало работать.

Другая возможность состоит в том, что приложение просто закрывается (то есть пользователь убил его, выключение компьютера, отключение питания и т. Д.). Я думаю, что ваша временная ключевая идея будет работать для этого. Это похоже на то, как программы редактирования текста, такие как vi или Word, автоматически создают специальную копию редактируемого файла. После открытия он проверяет, существует ли специальная копия, и спрашивает, хотите ли вы восстановить файл.

0 голосов
/ 17 ноября 2009

Я собираюсь подражать Маркосу здесь. Создайте файл конфигурации или журнала, в котором будет размещено последнее сообщение об ошибке и дата последнего запуска программы. Затем прочитайте этот файл во время загрузки программы.

0 голосов
/ 17 ноября 2009

Что я делаю, так это перенаправляю 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) {}
...