ShutdownHookがどのシグナルで呼び出されるか確認した
やりたいこと
JavaプログラムでaddShutdownHookに指定したThreadがどのシグナルで終了したときに呼び出されるのかを確認する。
確認方法
- 以下のJavaプログラムを実行する
- 起動したプログラムにkillコマンドでシグナルを投げて「call shutdown hook」が標準出力に出るか確認する。
public class SignalTest { public static void main(String [] args) { Runtime.getRuntime().addShutdownHook(new Thread( () -> System.out.println("call shutdown hook") )); while(true) { try { Thread.sleep(5000); System.out.println("exec..."); } catch (InterruptedException e) { e.printStackTrace(); } } } }
確認対象のシグナルは以下の4つ
- SIGINT(2)
- SIGQUIT(3)
- SIGTERM(15)
- SIGKILL(9)
確認環境
- OS
- Ubuntu 16.04.4 LTS
- Kernel
- 4.4.0-119-generic
- javac
- javac 1.8.0_162
- java
- openjdk version "1.8.0_162"
- OpenJDK Runtime Environment (build 1.8.0_162-8u162-b12-0ubuntu0.16.04.2-b12)
- OpenJDK 64-Bit Server VM (build 25.162-b12, mixed mode)
確認結果
SIGINT(2)
呼び出された。
$ java SignalTest exec... call shutdown hook
$ kill -2 pid
SIGQUIT(3)
呼び出されない。
Javadumpが出力され、処理が継続している。
$ java SignalTest exec... exec... exec... exec... exec... 2018-04-08 10:35:05 Full thread dump OpenJDK 64-Bit Server VM (25.162-b12 mixed mode): "Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007f2b580c8000 nid=0x81e runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007f2b580c3800 nid=0x81d waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f2b580bf000 nid=0x81c waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f2b580bd000 nid=0x81b waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f2b580ba000 nid=0x81a waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f2b580b8000 nid=0x819 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f2b58090800 nid=0x818 in Object.wait() [0x00007f2b1f0ce000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000071a208ec0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) - locked <0x000000071a208ec0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164) at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:212) "Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f2b5808c000 nid=0x817 in Object.wait() [0x00007f2b1f1cf000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000071a206b68> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x000000071a206b68> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) "main" #1 prio=5 os_prio=0 tid=0x00007f2b5800a800 nid=0x80b waiting on condition [0x00007f2b5fe1e000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at SignalTest.main(SignalTest.java:10) "VM Thread" os_prio=0 tid=0x00007f2b58084000 nid=0x816 runnable "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f2b5801f800 nid=0x80c runnable "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f2b58021800 nid=0x80d runnable "GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f2b58023000 nid=0x80e runnable "GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f2b58025000 nid=0x80f runnable "GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007f2b58026800 nid=0x810 runnable "GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007f2b58028800 nid=0x811 runnable "GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00007f2b5802a000 nid=0x812 runnable "GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00007f2b5802c000 nid=0x813 runnable "GC task thread#8 (ParallelGC)" os_prio=0 tid=0x00007f2b5802d800 nid=0x814 runnable "GC task thread#9 (ParallelGC)" os_prio=0 tid=0x00007f2b5802f000 nid=0x815 runnable "VM Periodic Task Thread" os_prio=0 tid=0x00007f2b580ca800 nid=0x81f waiting on condition JNI global references: 309 Heap PSYoungGen total 148992K, used 7680K [0x000000071a200000, 0x0000000724800000, 0x00000007c0000000) eden space 128000K, 6% used [0x000000071a200000,0x000000071a980098,0x0000000721f00000) from space 20992K, 0% used [0x0000000723380000,0x0000000723380000,0x0000000724800000) to space 20992K, 0% used [0x0000000721f00000,0x0000000721f00000,0x0000000723380000) ParOldGen total 339968K, used 0K [0x00000005ce600000, 0x00000005e3200000, 0x000000071a200000) object space 339968K, 0% used [0x00000005ce600000,0x00000005ce600000,0x00000005e3200000) Metaspace used 3490K, capacity 4632K, committed 4864K, reserved 1056768K class space used 380K, capacity 459K, committed 512K, reserved 1048576K exec... exec...
$ kill -3 pid
SIGTERM(15)
呼び出された。
$ java SignalTest exec... exec... exec... call shutdown hook
$ kill -15 pid
SIGKILL(9)
呼び出されない。
最後の「強制終了」はjvmの出力?と思われる。javadocの記述通りの挙動になった。
$ java SignalTest exec... exec... exec... 強制終了
$ kill -9 pid