Java

Java – スレッドダンプの取り方 その3 / Windows サービスとして登録している場合は?

その1 / スレッドダンプの取り方
その2 / Linux だと java プロセスがいっぱい!?
→その3 / Windows サービスとして登録している場合は?
その4 / WebLogic Server とスレッドダンプ
スレッドダンプの読み方 その1 – VM 内部スレッドと main スレッド

Windows 環境で、サーバサイドのプログラムは Windows サービスとして登録して運用することが多いです。

例えば Tomcat 5.5 であれば
%TOMCAT_HOME%¥bin¥service.bat install [サービス名]
でサービス登録、
> net start [サービス名]
で起動できます。(もちろんサービスコントロールパネルでもOk)


Tomcat5.5 が Widnows サービスとして起動した様子

しかし、このコマンドプロンプトは Tomcat のプロセスに直接絡んでいないため、Ctrl+Break は効きません。
そんなときに便利なのが SendSignal です。
これは指定したプロセスに Ctrl+Break を押下したのと同じ信号を送る、まさにスレッドダンプを取るために作られたプログラムです。
使い方は簡単、
> SendSignal [プロセスID]
とするだけ。

プロセスID は Windows のタスクマネージャで確認できます。
ただし、デフォルトではプロセスIDは表示されないため、[表示>列の選択]より[PID(プロセスID)]を選択しておく必要があります。
Tomcat をサービスとして起動している場合は java.exe ではなくtomcat5.exe として表示されます。
この↓例だと 1204 が Tomcat のプロセスID になります。

tomcat5.exe のプロセスID を確認中

プロセスID が確認できたら後は SendSignal の出番です。
> SendSignal.exe 1204 で Ok。

tomcat5.exe の出力は %TOMCAT_HOME%¥logs¥jakarta_service_yyyymmdd.log に記録され、スレッドダンプもここに出ます。
余談ですがこのファイルは改行コードが CRLF になっていないみたいで、メモ帳で開くとTSV形式(Tofu Separated Value – 豆腐区切り)の長い一行に見えてしまいます。
少し洒落たエディタとかとかで開きましょう。
さらに余談ですが標準出力・標準エラー出力は stderr|out_yyyymmdd.log というファイルに記録されています。これは(たぶん) Tomcat がアプリケーションレベルで補足して出力しているもので、JVM のもっと低レベルなところで出力されるスレッドダンプは記録されないことに注意してください。


SendSignal でスレッドダンプが出力された様子

SendSignal はスレッドダンプを取得するためだけに Windows サービス化をためらっていた人には非常にカユい所に手がとどく便利ツールなのですが、別のカユい制限があります。
バッチの中で呼び出すと “バッチ ジョブを終了しますか (Y/N)?” とバッチが停止してしまうのです。
どうやら Ctrl+Break の信号を自身も感知してしまう(?)ようで・・・。
一応回避策はあって、”start” を介して別のコマンドプロンプトをキックすれば大丈夫です。こんな↓感じで。
-send.bat

echo スレッドダンプを取得します。
start SendSignal [pid]
echo スレッドダンプを取得しました。

スレッドダンプの取得にはもう一つお勧めのツールがあります。
その名もズバリ、StackTrace。StackTrace とは各スレッドのメソッド呼び出し順のことです。NullPointerException とか発生したときにずらずらっと表示されるアレ。
Java Web Start としてパッケージされているので、JDK がインストールされている環境ならば起動は簡単、起動用のリンクをクリックするだけです。
よく使う場合はショートカットをデスクトップに配置することもできます。
使い方は簡単。起動したらメニューより [Process>Thread Dump…] を選んでプロセスID を入力するだけ。プロセスID がまだわかっていなければ一覧から選択することもできます。
StackTrace が賢いのはスレッドダンプがプロセスの向こう側に吐かれるのではなく、StackTrace のアプリケーション内で直接スレッドダンプを確認できることです。


StackTrace でスレッドダンプを取得している様子

ただ、かなりトリッキーな事をしているようで、スレッドダンプを取得する際、解析対象 JVM 内に勝手に “StackTrace Remote Thread” という名前のスレッドを作ってしまいます。
ちょっと使ってみた限り不安定になるようなことはありませんでしたが、どの程度の実績がある製品なのかは知りません。
動作中の JVM に影響を与えずに中身を確認できるのがスレッドダンプの良いところですので、やや気持ちが悪いといえば気持ちが悪いです。
冗長化していない環境では念のため、運用前に十分に検証しておきましょう。

ちなみに StackTrace は一部ネイティブライブラリを使っており、Pure Java のプログラムではありません。Mac OS X、Linux、Windows にのみ対応しています。

次回は WebLogic Server を利用している環境でのスレッドダンプの取り方について説明します。