Javaでシグナルを捕まえる方法
Linuxのkillコマンドなどで投げるシグナルをJavaで捕まえる方法について。
下記、シグナルを捕まえたらlog4jのログレベルを変更するコードを書いてみた。
package jp.sample.signal.log4j.main; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import sun.misc.Signal; import sun.misc.SignalHandler; public class SignalLog4jMain { static Log log = LogFactory.getLog(SignalLog4jMain.class); static int num = 1; public static void main(String[] args) { Signal signal = new Signal("TERM"); System.out.println("Default Signal Number: " + signal.getNumber()); Signal.handle(signal, new SignalHandler() { public void handle(Signal signal) { Logger rootLogger = LogManager.getRootLogger(); if (rootLogger.getLevel().equals(Level.INFO)) { rootLogger.setLevel(Level.DEBUG); } else { rootLogger.setLevel(Level.INFO); } num++; } }); while (true) { try { Thread.sleep(5000); Logger rootLogger = LogManager.getRootLogger(); System.out.println("Log Level: " + rootLogger.getLevel()); if (log.isDebugEnabled()) { log.debug("DEBUG LOG !!\n"); } if (log.isInfoEnabled()) { log.info("INFO LOG !!\n"); } } catch (Exception e) { e.printStackTrace(); } } } }
5秒毎にログを吐く。
下記でアプリケーションに対してシグナルを投げる。
kill -TERM [JavaアプリのPID]
シグナルはソースコード中でシグナル名で設定している。
Signal signal = new Signal("TERM");
Linuxでは「kill -l」を実行すると下記のようにシグナルの一覧が表示される。
$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 35) SIGRTMIN 36) SIGRTMIN+1 37) SIGRTMIN+2 38) SIGRTMIN+3 39) SIGRTMIN+4 40) SIGRTMIN+5 41) SIGRTMIN+6 42) SIGRTMIN+7 43) SIGRTMIN+8 44) SIGRTMIN+9 45) SIGRTMIN+10 46) SIGRTMIN+11 47) SIGRTMIN+12 48) SIGRTMIN+13 49) SIGRTMIN+14 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
この一覧では「SIG〜」のような名前で表示される。
実際にkillコマンドでシグナルを投げる際は「SIG」を外して指定する必要があることに注意。
例えば「SIGHUP」のシグナルを送りたいときは、「kill -HUP [PID]」と実行する必要がある。
また、HotSpotVMは下記のシグナルを使用しており、アプリケーションでシグナルを使用したい場合には下記を避けて選択する必要がある。
- SIGSEGV
- SIGBUS
- SIGFPE
- SIGPIPE
- SIGILL
- SIGQUIT
- SIGTERM
- SIGUSR1
- SIGUSR2
- SIGABRT
ソース:http://www.oracle.com/technetwork/java/javase/signals-139944.html
Linuxのシグナルまとめ
http://www.xmisao.com/2013/11/10/linux-kill-signals.html