どんなJavaアプリやjarライブラリでもデバックする方法(eclipseによるリモート・アタッチ)

今では、開発の様々なシーンでオープンソースのライブラリを使うことが多くなってきています。

そんなライブラリを使用する際に、想定しない動きをしたり、うまく動かないんだけど、中で何が行われているかわかりにくいこと、ありますよね。

自分で作成したクラスやアプリならEclipseのデバッグ機能を使えば、変数に何が入っているかなどを逐次実行できますが、オープンソースのスタンド・アロンアプリやWebサーバ上のWebアプリだと、そうは行きません。

そんなときに役立つTipsをご紹介します。

Eclipseで実行できないなら、実行中のJVMにつないで覗いてみる

その方法は、JVMに、リモートから接続してデバッグするというものです。

Javaのアプリやサーバはバーチャルマシン(JVM)上で実行されているというのはご存知ですよね。JVMにはもともと、デバッグ機能を外部に公開する仕様が備わっており、それを利用すると、Eclipseなど、他のJavaアプリから接続して、デバッグを行えるようになります

1.デバッグを外部から受け付けられる状態にする

外部からそのJVMに接続してデバッグを出来るようにするためには、JVMの起動時に、下記のようなオプションを渡す必要があります。

アプリやサーバの起動バッチファイルの中でJVMオプションを指定している部分があればそこに、なければ、Javaの実行時に以下の引数を指定します。(最後の「-jar remotedebugtest.jar」は実行するjarファイルの指定ですので、お使いの環境に合わせて変更してください。その前までの引数が重要です。)

java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=y -jar remotedebugtest.jar

それぞれの意味を解説すると、

  • -Xdebug・・・このJVMでデバッグを行うという意味になります。
  • -Xrunjdwp:・・・これ以降が、デバッグの詳細な振る舞いを指定するオプションです。
  • transport=dt_socket・・・接続をソケット形式で行う指定になります。他に共有メモリーも使用できますが、多くの場合はソケット形式でしょう。
  • server=y・・・デバッグ情報をどこで生成するかの指定です。yだと、接続先のJVMで行うことになります。
  • address=8000・・・Eclipseとのデバッグクライアントからの接続をそのポート受け付けるかのポート番号です。8000番台等、他のサーバと重ならない、適当なポート番号を指定します。
  • suspend=y・・・これは、少し癖があります。「y」だと、デバッグクライアントから接続するまで、アプリが実行されずに待ったままになります。すぐに実行して終わってしまうアプリは「y」の方がよいでしょう。逆に指定しないと待たずに実行されます。サーバ上に配備されるWebアプリは、指定しないほうが良いと思います。

2.Eclipseから接続する

上記オプションでアプリを起動したら、今度は、Eclipse側の設定を行って接続しましょう。

はじめに、適当なプロジェクトを作成します。

次に「実行」⇒「デバッグの構成」を開くと、上記のような設定画面が開きます。ここで、「リモートJavaアプリケーション」を右クリックすると、新規に構成が追加できます。

追加する構成の設定で、接続プロパティーにサーバのアドレス(ホストの部分)、ポートを入力します。

上記の起動時の引数だと、JVM側は、8000番で待ち受けているのですよね。

3.デバッグ可能な状態にする

さて、こここからも結構重要なポイントです。

どうやってステップ実行するかということです。ステップ実行するためには、上記で作成したプロジェクトのクラスパスに、デバッグする対象のクラスが含まれている必要があります。

イメージでいうと、リモートJVMで実行しているクラスファイルと、クライアントのEclipse側のプロジェクトのクラスファイルを指紋のように比較して、同じ形があれば、そこが実行されているとみなす感じでデバックしていくからです。

また、同じ形があったら、そのソースを表示するので、jarに、ソースをアタッチする設定を行っておきましょう。

ソースの無いjarであれば、jad等を利用して、Eclipseでデコンパイルしたソースを作ってプロジェクトに含めておくと、どんなアプリでもデバッグできます。