Javaプロセスが強制終了する。ShutdownHookとXrs

環境としてはこんな感じ

  • OS:Windows2003Server
  • Java:JDK5
  • Tomcatとかexeとかから、不定期にjavaコマンドでjarを実行するアプリケーション

事象としては

  • 実行タイミングは不定期、実行時間は数秒〜数時間(処理データ数に依存)
  • 問題なく動くのだが、時々理由がなくプロセスが吹っ飛ぶ(cmd.exe & java両方)

という感じ。理由なく吹っ飛び、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
  • CTRL_CLOSE_EVENT
  • 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

ブログ開設

眠い、飲み会から帰ったらこんな時間。

昨日・今日とデブサミ2010に行ってきて、かなり刺激になったんですよ。

で、いくつかのセッションで出てきてる言葉として
車輪の再発明
があったんですよ。

まあ用語自体はよく使われる言葉だとは思うのですが。

ただ、おいらは車輪の発明に助けられているなって思ったんですよね、よしおりさんのセッションを聞いて。

IT業界ってのはブログとかtwitterとかやっている割合が「きっと」異常なほど高くて、みんなが情報を発信している。
そのため、技術的とかハード的に問題が発生したときにgoogle先生に聞くと結構な確率でHitすることはよくあること。
そう、これって発明済みの車輪に助けられているってこと。

このことって、目から鱗だったりして、自分が誰かの車輪に助けられているのなら、自分発の車輪が誰かを助けるかもしれない!って感じで。

つーことでブログ開始。Bloggerと悩んだけどはてなで。

文章が雑すぎるのは、眠さと酔い。
でも、今日開始しないとまた理由を付けてやらなそうなので、意地でも今日から開始。