Javaでシグナルをキャッチする

linuxではお馴染み、シグナルをjavaでキャッチする方法です。
SIGHUPをキャッチします。

vim sample.java

import sun.misc.Signal;
import sun.misc.SignalHandler;

class SignalTest {
        static int sig = 0;
        public static void main(String[] args) {
                Signal signal = new Signal("HUP");
                Signal.handle(signal, new SignalHandler() {
                        public void handle(Signal sigInst) {
                                sig = 1;
                        }
                });
                while(sig == 0); 
        }
}                                                                                       

これをコンパイルして起動して別端末から、kill -HUP SinalTestのPID
をしてもプロセスがしなかった。


原因は、whileループで参照しているsigが最適化されて毎回参照していないためだ。
C言語でも最適化によって、この問題がおこるので、sig変数のみ最適化しないようにするための宣言があるそれが、
volatileです。javaでもあったので、使ってみた。

上のソースをsig変数をvolatile宣言する。こんな感じ。

volatile static int sig = 0;

これをコンパイルして起動して別端末から、kill -HUP SinalTestのPID
をするとちゃんと無限ループを抜ける。