Проблема запуска завершение работы крюка в Java

Я пытаюсь заставить крюк выключения работать в Java. Цель этой ловушки - записать в файл журнала, что программа была прервана. Приложение java скомпилировано в файл jar и выполнено с использованием командного файла, что означает, что вывод приложения идет в окно cmd.exe. Когда это окно cmd закрыто, я хочу, чтобы приложение регистрировало его закрытие.

Приложение предназначено для запуска на неопределенный срок и выполнения определенных задач в определенное время. Поэтому программа выполняет серию проверок в цикле "Пока истинно". Я не понимаю, почему этот хук не будет регистрировать, что приложение закрывается!

В основном методе мы имеем:

final Thread mainThread = Thread.currentThread();
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable()
{
    @Override
    public void run()
    {
        try { mainThread.join(); }
        catch (InterruptedException e) { }
        mission.log("Program Closed.", true);
    }
}
));

Вся "миссия" - это мой собственный класс, который выполняет регистрацию данных. Когда вы вызываете метод "log", он имеет BufferedWriter и вызывает его методы.write(), .newLine() и.flush().

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

4 ответа

Решение

Принудительно убивает приложение, то есть не грациозно, поэтому JVM не знает, что приложение закрывается, поэтому перехватчики завершения не вызываются.

К сожалению, нет способа (по крайней мере в Windows) предоставить механизм, который гарантирует, что ловушка всегда вызывается. Это просто то, что может быть вызвано, но нет никакой гарантии.

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

Однако, если вы удалите код

    try { mainThread.join(); }
    catch (InterruptedException e) { }

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

Сравните принятый ответ " Как изящно обрабатывать сигнал SIGKILL в Java", который содержит еще один пример того, что вы пытаетесь сделать.

Все здесь правы - вы не можете зарегистрировать принудительную остановку в вашей программе. Однако вы можете рассмотреть возможность использования другой программы для "наблюдения" за вашей программой и ожидания ее завершения. Программа 'watcher' может затем зарегистрировать завершение исходной программы и затем выйти сама.

Закрытие окна убивает процесс, поэтому отключение не будет работать.

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

Другие вопросы по тегам