Как изящно обрабатывать сигнал SIGKILL на Java
как вы справляетесь с очисткой, когда программа получает сигнал убийства?
например, есть приложение, к которому я подключаюсь, которое хочет, чтобы любое стороннее приложение (мое приложение) отправляло finish команда при выходе из системы. Что лучше всего сказать, чтобы отправить это finish команда, когда мое приложение было уничтожено с kill -9?
изменить 1: убить -9 не может быть захвачен. Спасибо, ребята, что поправили меня.
edit 2: я думаю, этот случай будет, когда один звонит просто убить, что то же самое, что ctrl-c
5 ответов:
способ справиться с этим ничего другое чем
kill -9было бы зарегистрировать остановка крюк. Если вы можете использовать (SIGTERM)kill -15крюк выключения будет работать. (SIGINT)kill -2тут вызвать программу, чтобы корректно завершить работу и запустить рычаги завершения работы.регистрирует новую виртуальную машину рычаг завершения работы.
виртуальная машина Java завершает работу в ответ к двум видам событий:
* The program exits normally, when the last non-daemon thread exits orкогда выход (эквивалентно, Система.exit) вызывается метод, или
* The virtual machine is terminated in response to a userпрерывание, например ввод ^C или a системные события, такие как выход пользователя из системы или выключение системы.
я попробовал следующую тестовую программу на OSX 10.6.3 и на
kill -9это ничего не запустите крюк выключения, не думал, что это будет. Наkill -15это тут запустите крюк выключения каждый время.public class TestShutdownHook { public static void main(final String[] args) throws InterruptedException { Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { System.out.println("Shutdown hook ran!"); } }); while (true) { Thread.sleep(1000); } } }нет никакого способа действительно изящно обращаться с
kill -9в любой программе.в редких случаях виртуальные машина может прерваться, то есть остановиться бег без выключения чисто. Это происходит, когда виртуальная машина завершается внешне, например с сигналом SIGKILL на Unix или Вызов TerminateProcess на Microsoft Окна.
единственный реальный вариант для обработки
kill -9is to попросите другую программу-наблюдатель следить за вашей основной программой, чтобы уйти или использовать сценарий обертки. Вы могли бы сделать это с помощью сценария оболочки, который опросил ищем программу в списке и действовать соответственно, когда он исчез.#!/usr/bin/env bash java TestShutdownHook wait # notify your other app that you quit echo "TestShutdownHook quit"
здесь are способы для обработки ваших собственных сигналов в определенные виртуальные машины -- см. эта статья о HotSpot JVM например.
С помощью внутреннего Солнца
sun.misc.Signal.handle(Signal, SignalHandler)вызов метода, вы также можете зарегистрировать обработчик сигнала, но, вероятно, не для сигналов типаINTилиTERMкак они используются JVM.чтобы иметь возможность обрабатывать любой сигнал вам придется прыгать из JVM и в операционную систему территория.
то, что я обычно делаю (например) для обнаружения ненормального завершения, - это запуск моей JVM внутри скрипта Perl, но сценарий ждет JVM с помощью
waitpidсистемный вызов.затем мне сообщают, когда JVM выходит, и почему он вышел, и может предпринять необходимые действия.
можно использовать
Runtime.getRuntime().addShutdownHook(...), но вы не можете быть уверены, что он будет называться в любом случае.
Я ожидал бы, что JVM изящно перебивает (
thread.interrupt()) все запущенные потоки, созданные приложением, по крайней мере для сигналовSIGINT (kill -2)иSIGTERM (kill -15).таким образом, сигнал будет передан им, что позволит изящно отменить поток и завершить ресурс в стандартные способы.
но это не случай (по крайней мере, в моем JVM реализация:
Java(TM) SE Runtime Environment (build 1.8.0_25-b17), Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode).как прокомментировали другие пользователи, использование выключение крючки кажется обязательным.
Итак, как бы я справился с этим?
Ну во-первых, я не забочусь об этом во всех программах, только в тех, где я хочу отслеживать отмены пользователей и неожиданные концы. Например, представьте, что ваша программа java-это процесс, управляемый другим. Вы можете различать, был ли он завершен изящно (
SIGTERMот процесс диспетчера) или произошло завершение работы (чтобы автоматически перезапустить задание при запуске).в качестве основы я всегда делаю свои длительные потоки периодически осведомленными о прерванном состоянии и бросаю
InterruptedExceptionесли они прерваны. Это позволяет завершить выполнение способом, контролируемым разработчиком (также создавая тот же результат, что и стандартные операции блокировки). Затем, на верхнем уровне стека потоков,InterruptedExceptionзахватывается и выполняется соответствующая очистка. Эти потоки закодированы для известных способов ответа на запрос прерывания. Высокий единство дизайн.Итак, в этих случаях я добавляю крюк выключения, который делает то, что, по моему мнению, JVM должен делать по умолчанию: прерывать все не-демонические потоки, созданные моим приложением, которые все еще работают:
Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { System.out.println("Interrupting threads"); Set<Thread> runningThreads = Thread.getAllStackTraces().keySet(); for (Thread th : runningThreads) { if (th != Thread.currentThread() && !th.isDaemon() && th.getClass().getName().startsWith("org.brutusin")) { System.out.println("Interrupting '" + th.getClass() + "' termination"); th.interrupt(); } } for (Thread th : runningThreads) { try { if (th != Thread.currentThread() && !th.isDaemon() && th.isInterrupted()) { System.out.println("Waiting '" + th.getName() + "' termination"); th.join(); } } catch (InterruptedException ex) { System.out.println("Shutdown interrupted"); } } System.out.println("Shutdown finished"); } });полное тестовое приложение на github:https://github.com/idelvall/kill-test
есть один способ реагировать на убийство -9: то есть иметь отдельный процесс, который контролирует процесс убивают и очищает после него, если это необходимо. Это, вероятно, будет связано с IPC и будет довольно много работы, и вы все равно можете переопределить его, убив оба процесса одновременно. Я предполагаю, что это не стоит в большинстве случаев.
тот, кто убивает процесс с -9 теоретически должны знать, что он/она делает, и что он может оставить вещи в несогласованное состояние.
Comments