Javaでの信号処理

私は、ある種のJavaサービスを作成するタスクにしばしば直面しました。 ほとんどの場合、OSとしてLinuxを使用しているため、このようなサービスを管理するのが最も便利です。デーモンと同様にサービスを操作するのが最も便利です。 つまり、次を実行します。
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コマンドはSIGTERMシグナルをJVMに送信し、サービスが停止します。 サービスの完了時にアクションを実行する必要がない限り、すべてが悪くないかのように、JVMは正常に完了します。 たとえば、リソースを明示的に解放したり、stdoutで何かいいことを書いたりします。

しかし、1.3.1以降のJVMではシグナルを処理できるため、すべてがそれほど怖いわけではありません。 答えとして-habrakatの下で。

信号を処理するために、私はかつて簡単なヘルパークラスを作成しました。
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 .

それだけです、複雑なことは何もありません。 ハンドラーで必要なアクションを実行すると、アプリケーションが終了します。

このトピックでは、最も単純なユースケースを示しました-SIGINT、SIGTERM、およびSIGABRTをキャッチします。 実際、はるかに多くの異なる種類の信号、およびそれらの使用オプションがあります。 ここで詳細な説明を参照してください。
http://www.ibm.com/developerworks/ibm/library/i-signalhandling/


Source: https://habr.com/ru/post/J78035/


All Articles