Javaプロセスのスレッドダンプを取るツール(ツール検索編)
某社の製品で,親プロセスのexeから生成したjavaアプリのプロセスのスレッドダンプを取得するというコマンドがあった。
Windowsでは,javaプロセスにCtrl+Breakを送るとスレッドダンプを取得できる。でも,普通はCtrl+Breakは,コンソールから起動したjavaプロセスにしか送れない。このコマンドはどうやってスレッドダンプを取ってんのかな?というのが気になった。
javaのスレッドダンプを取ってもデッドロックしてるかどうか調べるぐらいしか使い道は思いつかんけど,気になって調べてみたらいろいろ面白かったので書いてみる。
コマンドを実行してスレッドダンプを取得するということは当然キーボードからはCtrl+Breakは送ってない。Ctrl+Break相当のイベントを生成するWindowsのAPIがなんかあってそれを使ってるんでしょう。ということで調べたらあった。
GenerateConsoleCtrlEventの引数にCTRL_BREAK_EVENTを設定すればいいらしい。なるほど,簡単やな。
しかし,よくみるとこのAPIは同じプロセスグループにしかCtrl+Breakを送れんらしい。関係ないプロセスには送れんじゃないか。うーむ,これじゃないんかな?しかしほかに関係ありそうなAPIは見当たらん。Win32APIは詳しく知らんけど,コマンドから直接javaプロセスにGenerateConsoleCtrlEventを送っているわけではないらしい。
よく考えるとjavaプロセスは親プロセスのexeから起動してるから,どうやらこいつが送っているらしい。コマンドはjavaプロセスの親プロセスにスレッドダンプ下さいって言うだけで,実際にGenerateConsoleCtrlEvent実行してんのはjavaプロセスの親プロセスってことみたいです。ふーむ。普通にやろうとすると,こういう仕組みにするしかないよな。
スレッドダンプ +------------+ 下さ〜い +--------------+ | コマンド | −−−−→ | 親プロセス | +------------+ +--------------+ | GenerateConsoleCtrlEvent実行。 ↓ スレッドダンプちょうだ〜い。 +---------------+ | java hogehoge | +---------------+
しかし,これだと全く汎用性がなくてこういう作りをしてるプログラムにしか使えんな。イマイチおもしろくない。任意のjavaプロセスから直接スレッドダンプを取れるツールはないんかな?絶対あるはず,と思って探してみた。
jstackというJDK付属のコマンドでスレッドダンプが取れるらしいけど,Windowsで使えるようになるのはMustangかららしい。んーおしいな。もうちょい。
いろいろ検索してると,どうもSendSignalというやつがそうらしいということが分かった。LateNightHackingっていうかなりキワドイ名前のサイトで公開されてる…あやしい。そして作者Louisの自己紹介は自己主張全開である。
とりあえず実行してみた。
おおっ!できた!すげー!別のコンソールで実行してるjavaプロセスや,javawからでもスレッドダンプが取れる!凄いぞLouis!さすが本場のはっかーは馬力が違うぜ!たまにアプリケーション例外が出るけど全然オッケーだ!
このツールは使える。いや,使い道は少ないけどなんかそそられる。