Java

Java – スレッドダンプの取り方

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

スレッドダンプの読み方 その1 – VM 内部スレッドと main スレッド

スレッドダンプの取得方法、解析方法について網羅的に説明した資料はあまりないのでちょっと書いてみました。まとまったらのドキュメントに追加するつもりです。

スレッドダンプとは、 Java のプロセス内部で動作している各スレッドがそれぞれ何をしているか確認できるものです。
Java のプログラムがフリーズした場合や、パフォーマンス低下が見られる場合などに取得すると、どのスレッドが停滞しているのか、プログラム中具体的にどこで止まっているのかを解析できます。

スレッドダンプは任意のタイミングで SIGQUIT シグナルを送る(Unix)、または キーボードで Ctrl+Break を押下する(Windows)ことで取得できます。
JVM のベンダやバージョンにより異なりますが、多くの場合スレッドダンプは標準出力、または標準エラー出力に記録されます。
簡単にまとめるとスレッドダンプは以下のような手順で解析することになります。
1. 標準出力/標準エラー出力のファイルへのリダイレクト
2. プロセスIDの確認
3. シグナルの送信
4. リダイレクト済みファイルよりスレッドダンプの確認

以下に手順の内容を具体的に説明します。

1. 標準出力/標準エラー出力のファイルへのリダイレクト
スレッドダンプはターミナルアプリケーションやコマンドプロンプト等から直接確認することもできますが、過去のログが流れて見えなくなってしまったり、検索操作ができなかったりと、大変苦痛を伴うのでアプリケーション起動時にファイルへリダイレクトしておくことをお勧めします。
例えば bash や Windows では以下のようにします。

$ [javaアプリケーションの起動スクリプト] > console.log 2>&1

例) > startWebLogic.cmd > console.log 2>&1

Windows の Tomcat など、起動スクリプト内で start コマンドを使って別DOS窓を起こしている場合は起動スクリプトそのものの出力をリダイレクトしてもだめです。
Tomcat の場合、具体的には catalina.bat の
———-
set _EXECJAVA=start “Tomcat” %_RUNJAVA%
goto gotTitle
:noTitle
set _EXECJAVA=start %_RUNJAVA%
———-
という部分を以下のように書き換えて、start コマンドを潰してから、
———-
set _EXECJAVA=%_RUNJAVA%
goto gotTitle
:noTitle
set _EXECJAVA=%_RUNJAVA%
———-

%CMD_LINE_ARGS% %ACTION% 以降に “>console.log 2>&1” を追加する必要があります(4箇所)。
———-
…. %CMD_LINE_ARGS% %ACTION% >console.log 2>&1
———-

なお、IBM 製の JVM ではスレッドダンプは標準出力、標準エラー出力とは別にファイルに記録されるため、スレッドダンプ取得の目的ではこの操作は必要ありません。

2. プロセス ID の確認、シグナルの送信
Unix 系OS (Mac OS X, Solaris, HP-UX, Linux, AIX等) の場合、SIGQUIT 信号を送るためにプロセス ID を確認する必要があります。
$ ps |grep java

例)
$ ps |grep java
344 p1 S+ 4:32.83 /System/Library/Frameworks/JavaVM.framework/Versions/1.4.2/Home/bin/java -Xms32m -Xmx200m
2787 p2 R+ 0:00.00 grep java

3. シグナルの送信
・Unix 系OS (Mac OS X, Solaris, HP-UX, Linux等) の場合
スレッドダンプを取得したいタイミングで kill コマンドを使いシグナルを送信します。”-3″ オプションを付けるのを忘れずに!
$ kill -3 [プロセスID]

例) $ kill -3 344

・Windows の場合
スレッドダンプを取得したい Java アプリケーションが起動しているコマンドプロンプトを最前面に持ってきて、キーボードの Ctrl と Break を同時に押下します。
Break キーは多くの場合キーボード上部右側辺りに位置しています。
ノートパソコンなどでは Fn キーと同時に押す必要がある場合があります。

4. リダイレクト済みファイルよりスレッドダンプの確認
スレッドダンプは決まったヘッダから始まります。スレッドダンプが記録されたファイルをエディタで開いて、以下のヘッダを確認してください。
・Sun / HP / Apple の JVM の場合
Full thread dump:
・BEA JRockit の場合
===== FULL THREAD DUMP ===============
・IBM の JVM の場合(※)
1XMTHDINFO Thread Info

※IBM 製の JVM ではスレッドダンプは JVM の起動ディレクトリに javacore.YYYYMMDD.nnnnnn.[pid].txt というファイル名で記録されます。


JRockit のスレッドダンプを確認している様子

次回はちょっと例外的な状況(Linux Threads を使っている場合Windows サービスとして起動している場合)でのスレッドダンプの取得方法について説明します。