ShutdownHookがどのシグナルで呼び出されるか確認した

やりたいこと

JavaプログラムでaddShutdownHookに指定したThreadがどのシグナルで終了したときに呼び出されるのかを確認する。

Runtime (Java Platform SE 8)

確認方法

  1. 以下のJavaプログラムを実行する
  2. 起動したプログラムに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
  • 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

iPhone8Plusを購入した

iPhone8Plusを購入した。前はAndroid端末を利用していたがもう2年ぐらい経っておりバッテリの劣化も激しいので買い替えたかった。iPhone8Plusは以下の理由で購入を決定した。

  • sim free端末が欲しかった
  • 電子マネーを利用したかった
  • ARアプリで遊んでみたかった
  • 新しく出てくるアプリでiOS版のみ(Androidは後でリリース)みたいなのが稀によくある
  • バッテリーの持ちが良い

iPhoneXは高いし、次期XがTrueDepth後面に配置されるかもみたいな情報を得て今買いどきではないなと判断した、iPhone8無印は持ちやすそうだけど、バッテリの持ちに不安を覚えたので最終的にPlusに落ち着いた。

外箱

f:id:hkou:20180304164448j:plain

開封①

f:id:hkou:20180304164652j:plain

開封②

f:id:hkou:20180304164733j:plain

端末

f:id:hkou:20180311083318j:plain

Suica

Suica物理カードを持っていなかったので、Suicaアプリから新規Suicaカード(記名式)を作成、Walletに登録した。 f:id:hkou:20180311083426j:plain

コンビニで利用してみたが、iPhoneがスリープ状態でもかざすだけですぐに決済できた(Suicaをエクスプレス・カードに設定している場合)
以前はmanacaをよく利用していたが、残高の確認がいちいち面倒だったのと、チャージが駅でしかできなかったので、それらが端末上ですぐにできるのは良いと感じた。 f:id:hkou:20180311083557j:plain

ひまわりの湯へ行ってきた

結構暖かくなってきたしバイクもたまには動かさなきゃと思い、近場のひまわりの湯へ行ってきた。
走り始めはそこまで寒くなかったけど、ひまわりの湯へ近づくにつれて非常に寒くなってきた。山の上の方にあるし近くにスキー場もあるようなところだから寒いのはあたりまえだ。 天気予報では晴れの予報だったが、午後に入ると曇ってきて余計に寒くなった。 f:id:hkou:20180224112552j:plain

温泉で身体を温めた後はいつもの定食をいただく。 f:id:hkou:20180224121112j:plain

ことぶきの湯へ行ってきた

唐突に温泉へ行きたくなった。名古屋近郊はまともな泉質の温泉が少ない。なのでちゃんとした温泉に入ろうとすると結構走らなければならない、まだ今は寒いので距離が遠いのは億劫になる。そんなことを考えていたら近場でもちゃんとした泉質の温泉があるという情報を得たので行ってみることにした。

f:id:hkou:20180211122440j:plain

外見は普通のスーパー銭湯っぽい。もちろん中もスーパー銭湯なんだけど、この温泉の露天風呂では三重県から天然温泉を持ってきているとのこと。
実際に入ってみると無色透明ではあるが、ぬるっとした感触がある、池田温泉や湯華の郷に近い泉質のようだ。
近場でこんなちゃんとした温泉に入れるのは結構感動する。 f:id:hkou:20180211122528j:plain

あと、この温泉に併設された食堂は値段が安い割にちゃんとした感じの食事が食べられて良かった。 f:id:hkou:20180211125930j:plain

北海道行ってきた(紋別→ガリンコタワー→網走刑務所→網走)

今日はガリンコ号に乗る予定だった。そして今日は今年初のガリンコ号出港日である、前日に電話予約して楽しみにしていたが朝電話がかかってきて「天候不順のため本日の出港は取りやめになりました」とのこと。
このときは「こんなにいい天気なのに出港できないってどういうこと」とか思ってたけど後でその理由が分かることになる。 f:id:hkou:20180111075206j:plain

出発

予定変更して今日はガリンコタワーへ向かうことにした。

車に雪が積もっていた f:id:hkou:20180111093226j:plain

車内に装備されていたブラシで雪を払い落としていく。全部払い落とすのは結構疲れた。 f:id:hkou:20180111093331j:plain

ガリンコタワー

ガリンコタワーはガリンコ号乗り場のすぐ近くにある。といっても長い通路を渡らなければならず一般車両は侵入禁止だったので送迎バスを利用した。 f:id:hkou:20180111100620j:plain

f:id:hkou:20180111100915j:plain

平日で開店したばっかりなので他の客がぜんぜん居なかった。 f:id:hkou:20180111101953j:plain

タワーまでの通路、人が多すぎるのも嫌いだけど自分ひとりだとそれはそれで寂しい。 f:id:hkou:20180111102243j:plain

通路の下は海で、一部床がガラス窓になっており下が覗けるようになっている。地味に怖い f:id:hkou:20180111102306j:plain

ガリンコタワーから見た海の様子。荒れに荒れまくってて、これは流石に欠航するわという気持ちになった。 f:id:hkou:20180111102907j:plain

海底区画

ガリンコタワーは海の中に立っており、最下層は海中に位置している。

f:id:hkou:20180111103815j:plain

壁がガラス張りになっているところがいくつかあり海中を覗くことができる。海が濁ってて外の様子は全然わからなかったが、この外が先程見たあの荒れた海の中だと思うと結構怖かった。 f:id:hkou:20180111104215j:plain

f:id:hkou:20180111104633j:plain

f:id:hkou:20180111105237j:plain

移動

ガリンコタワーを満喫したので次は網走に向かうことにした。

f:id:hkou:20180111120526j:plain

サロマ湖

f:id:hkou:20180111120504j:plain

基本的にこのような一直線の道がずーっと続いているので運転は楽なんだけど慣れてきて眠くなってしまう。眠くなるとちょくちょく休憩をしていた。 f:id:hkou:20180111132331j:plain

ホテル到着(網走)

結構早めの時間にホテルに到着した。時間に余裕があったのでチェックインしてすぐに網走刑務所へ行くことにした。 f:id:hkou:20180111141406j:plain

網走刑務所

f:id:hkou:20180111143347j:plain

f:id:hkou:20180111143639j:plain

f:id:hkou:20180111144226j:plain

f:id:hkou:20180111150201j:plain

f:id:hkou:20180111153340j:plain

f:id:hkou:20180111153600j:plain

f:id:hkou:20180111154608j:plain

北海道行ってきた(札幌→旭川→紋別)

今日は殆どの時間を移動に費やした日だった。最終目的地は紋別で、札幌から旭川は電車で向かい、旭川から紋別までは車で移動した。

ホテル(朝)

朝焼けが他のビルに反射してなかなか綺麗な景色。近代的なビル群とそのすぐ後ろに山々が見えるのも名古屋ではあまり見ない景色なので珍しかった。 f:id:hkou:20180110072625j:plain

札幌駅

旭川あたりで大雪になっておりその影響で電車が結構遅延していた。札幌は快晴だったけど旭川が豪雪だったらしい。駅ナカの待合室みたいなところで凍えながら電車を待っていた。結局1時間半ぐらい遅延してやっと電車に乗ることができた。 f:id:hkou:20180110112834j:plain

f:id:hkou:20180110110809j:plain

やっと電車に乗れた。 f:id:hkou:20180110121127j:plain

電車が進むに連れてどんどん天気が悪くなっていく。 f:id:hkou:20180110134145j:plain

旭川駅

結局当初の予定よりも2時間ぐらい遅れてやっと旭川駅に着いた。かなり余裕を持ったスケジュールにしていたのでレンタカーの時間にはギリギリ間に合った。ただ当初の予定では旭川駅に早めについて昼ごはん食べたり散策しようと思っていたのでそれができなくなって残念だった。 f:id:hkou:20180110140419j:plain

駅舎 f:id:hkou:20180110141035j:plain

レンタカー

駅すぐ近くのレンタカー屋で車を借りて運転した。長野や岐阜で雪道は少し走ったことある程度なので走り始めは結構不安だった。

f:id:hkou:20180110143502j:plain

道の境目(外側と中央線)が非常にわかりづらくて結構怖かった。

f:id:hkou:20180110150926j:plain

レンタカーはカローラになった。もともともう一段小さいグレードを借りたけど、車が用意できなかったとかでカローラになった。4WDで雪道でも安定して走行してくれて良かった。 f:id:hkou:20180110161137j:plain

殆ど休憩なしで走ってたけど夜になってしまった。紋別は結構遠い。 f:id:hkou:20180110164125j:plain

ホテル

やっとホテル到着。 f:id:hkou:20180110185332j:plain

結構夜遅目だったので周りの店は空いてなさそう&雪道歩いて移動するのもだるかったのであんまり期待せずにホテル内の食堂を利用したが、出てきた料理はいい意味で期待以上でなかなか美味しかった。 f:id:hkou:20180110191559j:plain

セイコーマート

タイミングが悪くてなかなか行けなかったセイコーマートがホテルの直ぐ側にあるようだったので行ってきた。 f:id:hkou:20180110202940j:plain

セイコーマートで買ってきたカツゲン。久しぶりに飲んだけどやっぱり美味しい f:id:hkou:20180110203632j:plain

北海道行ってきた(名古屋→札幌)

案件と案件の切れ間ができて長期休暇が取れたので、久しぶりに北海道へ行ってきた。

出発(中部国際空港

平日に出発したので、空港は人がいなくて快適だった。スカイデッキは強風のため閉鎖されてて残念だった。 f:id:hkou:20180109122730j:plain

飛行機に乗り込む。この瞬間はいつもワクワクしている f:id:hkou:20180109135957j:plain

飛行機

名古屋離陸後は晴れてて景色が良かった。 f:id:hkou:20180109151655j:plain

札幌上空、曇ってて天気も乱れていた。飛行機が結構揺れて気持ち悪くなったのとなかなか着陸せずずっと札幌の上空を旋回してたので気分が悪かった。 f:id:hkou:20180109154856j:plain

ホテル

気分がずっと悪かったので、寄り道せずにすぐにホテルへチェックインした。24階の部屋で夜景が一望できてなかなか良い部屋でした。 f:id:hkou:20180109173329j:plain

ばんごはん

ベッドで横になってたら、ある程度楽になったのでごはんを食べようと外に出た。 f:id:hkou:20180109181943j:plain

すみれラーメンを食べた。 f:id:hkou:20180109182950j:plain