特別なプラグイン無しでコンテナ(Tomcat)をデバッグする

Eclipse上でサーブレットコンテナを含めてWebアプリケーションをデバッグするには、最近であればWTP(Web Tools Project)や古くからあるSysdeoのTomcatプラグインを使うと便利なものだ。しかし私はそれらを使わない。
ただでさえ重いEclipseが更に重くなるのと、開発環境が対象のソフトウェアではなく、IDEとプラグイン(場合によってはJVM)のバージョンにロックインされる可能性が上がるのが嫌だったりする。あと、これらのプラグインは専用のプロジェクトを用意することを要求したり(WTPはそうだ)、元々動いているサーバの環境設定のクローンが必要だったりするのも面倒だ。
そもそもJavaで書かれているサーバ(現在であれば殆どがそうだろう)であればJDTの機能だけでデバッグできるのだ。

EclipseJ2SE 1.4から対応が始まったJava Platform Debugger Architecture (JPDA)機能を使ったデバッグが可能であり、パースペクティブで起動の設定を行っておけば、その設定を基にしてJPDAデバッグモードでの起動を実行できる。以下、Tomcat5.5を使うことを前提にしてその手順を書いておく。

1. 起動コマンドを調べる

Tomcatであれば%CATALINA_HOME%/bin/catalina.bat(.sh)を調べて、実行される際に発行されるコマンドラインを記録しておく。catalina.batなら"echo off"をコメントアウトして、最後に表示されたjavaコマンドをログにリダイレクトするか、範囲選択でコピーしておく。catalina.shであれば逆にコマンドラインのパラメタをechoで出力してやれば良いだろう。

私のWindows環境であればこんな感じの行だ。

C:\apache-tomcat-5.5.20\bin>start "Tomcat" "C:\javasoft\j2se1.6\bin\java" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file="C:\apache-tomcat-5.5.20\conf\logging.properties" -Djava.endorsed.dirs="C:\apache-tomcat-5.5.
20\common\endorsed" -classpath "%CLASSPATH%は環境依存するので略" -Dcatalina.base="C:\apache-tomcat-5.5.20" -Dcatalina.home="C:\apache-tomcat-5.5.20" -Djava.io.tmpdir="C:\apache-tomcat-5.5.20\temp" org.apache.catalina.startup.Bootstrap  start

ここからEclipseの実行時に使う行を抜き出す。
上の長い行を見ると"org.apache.catalina.startup.Bootstrap"というクラスが"start"というパラメタでJavaから起動されていることが解るだろう。また、"-D"をプレフィクスに持つパラメタはCATALINA_OPTSを介してJavaシステムパラメタとしてTomcatに渡されるものだ。クラスパスはEclipseで適切にプロジェクトが作られていれば、実行時に自動的に付加されるのでここでは必要ない。
なお、Tomcatの起動スクリプトcatalina.は外部IDEからアタッチしてデバッグできるように、JPDAのデバッグモードを持っているが、細かい設定はEclipseのJDT側で制御するのでここでデバッグモードを使う必要は無い。


2. EclipseのJDTで起動設定を作る

「実行 -> 構成及びデバッグ」を開き、Javaアプリケーションの実行/デバッグとして構成を作成する。
1.で取得したコマンドラインとパラメタで必要な箇所を埋めていくだけであり、簡単だ。

"メイン" タブ
プロジェクト -> デバッグする対象のプロジェクトを選択して入力
メインクラス -> org.apache.catalina.startup.Bootstrap (プロジェクトにbootstrap.jarがバインドされていないとエラーになる)

"引数" タブ
プログラムの引数 -> start
VM引数 ->

-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file="C:\apache-tomcat-5.5.20\conf\logging.properties" -Djava.endorsed.dirs="C:\apache-tomcat-5.5.
20\common\endorsed" -Dcatalina.base="C:\apache-tomcat-5.5.20" -Dcatalina.home="C:\apache-tomcat-5.5.20" -Djava.io.tmpdir="C:\apache-tomcat-5.5.20\temp"

この他にVMパラメタが必要な場合は、同様に追加する(例えば -Xmx512m など)。
以降の"JRE" タブ と"クラスパス" タブ は、一般的なアプリケーションをデバッグするのと変わりないので省略する。


3. 実行する

2.の設定が上手くできていれば、そのままメニューから実行すればTomcatが既存の設定のまま起動するし、デバッグ起動を行えばJPDAデバッグに必要なパラメタが起動時のコマンドラインに追加されてデバッグセッションが開始される訳だ。当然クラスとソースへのパスは通っているので、あとは自由にデバッグできるはずだ。

私の環境ではEclipseからデバッグ起動した際のプロパティ、つまりコマンドラインは以下のようになる。

C:\javasoft\j2se1.6\bin\javaw.exe -server -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=C:\apache-tomcat-5.5.20\conf\logging.properties -Djava.endorsed.dirs=C:\apache-tomcat-5.5.20\common\endorsed -Dcatalina.base=C:\apache-tomcat-5.5.20 -Dcatalina.home=C:\apache-tomcat-5.5.20 -Djava.io.tmpdir=C:\apache-tomcat-5.5.20\temp -classpath "クラスパスは長いし環境依存するので省略"  -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:50052 org.apache.catalina.startup.Bootstrap start

注目すべきは最後のBootStrapクラスの前に追加されたパラメタだ。ここがJPDAによるデバッグを行う記述となる。

-agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:50052 

この見慣れない"-agentlib:jdwp"はJava5(1.5)以降より変更されたJDWP エージェントのロードの指定方法だ(今回使用したJVMは1.4系ではないので"-Xrunjdwp"が使われていない)
JPDA 接続および呼び出しの詳細

なお、今回はEcliseを例にしたが、この方法は他のJPDAデバッグに対応した最近のJava IDEであればそのまま応用できるはずだ。(むしろEclipse以外のIDEを使っているのであれば今回のデバッグ方法は当たり前かもしれないが。)

この方法ではJSPを直接デバッグすることはできないのだし(私には不要だが)、ことさら便利なプラグインを否定するつもり無いが、なにより軽いしEclipseとJDTさえあればデバッグできるのは、私のようなへそ曲がりな理由以外にも使う時があるかもしれない。