Javaプロセスが強制終了する。ShutdownHookとXrs
環境としてはこんな感じ
事象としては
という感じ。理由なく吹っ飛び、Windowsとかのイベントにも残らないため、当初は
Javaが理由なく吹っ飛んだという理由で片付けられた問題。
自己防衛で言っておくと作ったのは、別チームだったのですがいろいろあってオイラが調査→対応することになった訳。
備忘録なので結果から言うと
Javaの仕様の一部
だったのですが、調査の経緯と仕様とまとめていきます。
調査1
とりあえず、try{}catch{}finally{}を仕込でみる。
逆に言うと例外関連の実装がなされていなかった訳なのですが。。。。。え゛?
try { System.out.println("Start"); // もろもろの処理 System.out.println("End"); } catch (Exception e) { System.out.println("Exception"); } finally { System.out.println("finally"); }
結果
やはり、javaプロセスが時々飛ぶ。
飛んだ時の標準出力(本当はログですが)はこんな感じ
Start
ということで、catch{}finally{}にうまく入っていないことが判明。
う〜ん。。。
調査2
ネットでいろいろ参照した結果、java.exeは以下のタイミングで終了する。
- CTRL_C_EVENT
- MS-DOS上で、ctrl+C
- CTRL_CLOSE_EVENT
- MS-DOSの×ボタン
- CTRL_LOGOFF_EVENT
- ユーザがログオフ
- CTRL_SHUTDOWN_EVENT
- PCをシャットダウン
ここで、原因が判明
- OSがWindows2003Server
- テスト時や運用時は、RDP(Remote Desktop Protocol)を利用してサーバにアクセスをする。
- RDPのログオフは、CTRL_LOGOFF_EVENTの起因となる。
- つまり、RDPでログオフするときにjavaプロセスが終了してしまう。
確かに、プロセスが飛ぶのはテストで、夜中に大量処理とか流しているときは問題なしだった
原因がわかったところで対応策を練ろう。
対応策
その1
シャットダウンフックを実装する
上記のイベント発生時は、VMがシャットダウンを行うため前述のtry{}catch{}finally{}は動かない。
じゃあ、終了処理はどうするのかっていうと、shutdownhookを実装する。
実装の仕方は簡単で
// ShutdownHookの設定 Thread shutdown = new Thread() { public void run() { System.out.println("Call ShutdownHook"); // 終了処理 } }; Runtime.getRuntime().addShutdownHook(shutdown); try { System.out.println("Start"); // もろもろの処理 System.out.println("End"); } catch (Exception e) { System.out.println("Exception"); } finally { System.out.println("finally"); } // ShutdownHookの削除 Runtime.getRuntime().removeShutdownHook(shutdown);
って感じ。
これで何を拾えるのかというと、RDPのログオフで終了した場合にそれが起きたことが拾えるようになる。
ただ、これだと根本的な解決(終了したことが拾えるけと、そもそも終了させたくない)にはならない。
対応策
その2
- Xrsオプションの付与
起動時に
java -Xrs 今までの起動コマンド
って感じにする。
このオプション設定で、上記のシャットダウンイベントに引きつられないようになるため、RDPのログオフても終了しなくなる。
ただし、このオプションは
- Ctrl + Breakが使えない
- System.exit(int)を必ず実装する必要がある
という、前提があるため採用する場合には検討事項がある。
おいらは採用しましたが。
やっぱり言語仕様とかVM仕様とかは、一度目を通しておこう!って思わされた問題だった。
(参考)
オプション-Xrs
http://java.sun.com/javase/ja/6/docs/ja/technotes/tools/windows/java.html
シャットダウンフックについて(java5)
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/lang/hook-design.html
シャットダウンフックについて(java6)
http://java.sun.com/javase/ja/6/docs/ja/technotes/guides/lang/hook-design.html