Передо мной частенько вставала задача написать какой-нибудь Java-сервис. В качестве ОС мы используем по большей части линукс, так что удобнее всего управляться с такими сервисами — работать с ними как с демонами. То есть, запускаем:
, и останавливаем:
Команда --stop посылает JVM сигнал SIGTERM и сервис останавливается. Все как бы неплохо, JVM завершается в штатном порядке, если только вам не нужно выполнить по завершении работы сервиса какое-либо действие. Например явно освободить ресурс, или написать что-нибудь приятное в stdout.
Но все не так страшно, благо JVM начиная с 1.3.1 позволяет обрабатывать сигналы. За ответом как — под хабракат.
Для обработки сигналов я в свое время написал простой вспомогательный класс:
Пример использования:
Вот и все, ничего сложного. В handler'е совершаем необходимые действия и приложение завершается.
В топике я привел самый простой вариант использования — отлавливаем SIGINT, SIGTERM и SIGABRT. На самом деле различных видов сигналов, как и вариантов их использования, намного больше. Более подробное описание смотреть здесь:
http://www.ibm.com/developerworks/ibm/library/i-signalhandling/
start-stop-daemon --start --make-pidfile --pidfile /var/run/myservice.pid --exec /usr/bin/java — -jar myservice.jar
, и останавливаем:
start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/myservice.pid
Команда --stop посылает JVM сигнал SIGTERM и сервис останавливается. Все как бы неплохо, JVM завершается в штатном порядке, если только вам не нужно выполнить по завершении работы сервиса какое-либо действие. Например явно освободить ресурс, или написать что-нибудь приятное в stdout.
Но все не так страшно, благо JVM начиная с 1.3.1 позволяет обрабатывать сигналы. За ответом как — под хабракат.
Для обработки сигналов я в свое время написал простой вспомогательный класс:
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class DiagnosticSignalHandler implements SignalHandler {
// Static method to install the signal handler
public static void install(String signalName, SignalHandler handler) {
Signal signal = new Signal(signalName);
DiagnosticSignalHandler diagnosticSignalHandler = new DiagnosticSignalHandler();
SignalHandler oldHandler = Signal.handle(signal, diagnosticSignalHandler);
diagnosticSignalHandler.setHandler(handler);
diagnosticSignalHandler.setOldHandler(oldHandler);
}
private SignalHandler oldHandler;
private SignalHandler handler;
private DiagnosticSignalHandler() {
}
private void setOldHandler(SignalHandler oldHandler) {
this.oldHandler = oldHandler;
}
private void setHandler(SignalHandler handler) {
this.handler = handler;
}
// Signal handler method
@Override
public void handle(Signal sig) {
System.out.println("Diagnostic Signal handler called for signal " + sig);
try {
handler.handle(sig);
// Chain back to previous handler, if one exists
if (oldHandler != SIG_DFL && oldHandler != SIG_IGN) {
oldHandler.handle(sig);
}
} catch (Exception e) {
System.out.println("Signal handler failed, reason " + e);
}
}
}
* This source code was highlighted with Source Code Highlighter.
Пример использования:
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class App {
private SomeVeryImportantResource resource;
public static void main(String[] args) {
SignalHandler signalHandler = new SignalHandler() {
@Override
public void handle(Signal sig) {
...
resource.release();
...
}
};
DiagnosticSignalHandler.install("TERM", signalHandler);
DiagnosticSignalHandler.install("INT", signalHandler);
DiagnosticSignalHandler.install("ABRT", signalHandler);
...
resource.lock();
...
}
}
* This source code was highlighted with Source Code Highlighter.
Вот и все, ничего сложного. В handler'е совершаем необходимые действия и приложение завершается.
В топике я привел самый простой вариант использования — отлавливаем SIGINT, SIGTERM и SIGABRT. На самом деле различных видов сигналов, как и вариантов их использования, намного больше. Более подробное описание смотреть здесь:
http://www.ibm.com/developerworks/ibm/library/i-signalhandling/