次はJavaのデバッガについて調べました。
背景
Javaプログラムの実行は、Java Virtual Machine(以下JVM)上に存在する仮想的なCPUがbytecode(仮想的なCPUが解釈する機械語)を解釈、処理をしていくことによって、行われます。
bytecodeはJavaコードをjavacでコンパイルしたときに生成されるコードでもあります。
JavaコードとCコード、bytecodeとアセンブリコードが、それぞれ似たような存在です。
OSから見た場合、JVMとJVM上で動くJavaプログラムは一つのプロセスにすぎません。
よって、OSが提供するデバッグAPIを用いたデバッガでJavaプログラムをデバッグすることが可能ですが、JVMの実行コード(アセンブリコード)やJVMが扱うデータ、JVM上で動くJavaプログラムの実行コード(bytecode)やJavaプログラムが扱うデータがごちゃごちゃしていて、デバッグするのは大変です。
JVM自身に関する情報とJavaプログラムに関する情報を切り分けて、デバッガ利用者へ提示するようにデバッガを実装すれば良いのですが、JVMの実装が変更になった時、それにあわせてデバッガを実装しなおす必要がでてきます。
また、実装の異なる複数のJVMに対応したデバッガを用意するのは困難ですし、デバッグAPIはOS依存なので、複数のOSで動作するデバッガを用意するのも困難です。
JPDAとそれを利用したデバッガ実装
そこで、Sunは、以下の3つの仕様を定めることで、JVMやOSの違いによる問題を解消しています*1。
- JVMTI(Virtual Machine Debug Interface)
- JVMが提供するデバッグ機能の仕様
- Javaプログラム上の変数情報の要求や、breakpointイベントの発生通知等の機能等
- JVMが提供するデバッグ機能の仕様
- JDWP(Java Debug Wire Protocol)
- debugeeとdebuggerでやり取りされるデバッグ情報や要求の形式に関する仕様
- JDI(Java Debug Interface)
- debugger側の実装に利用するpure Javaのインターフェイスに関する仕様
これら3つの仕様を総称してJPDA(Java Platform Debugger Architecture)と呼びます。
Sun自身が、各仕様を満たした、リファレンス実装を提供しているので、デバッガ製作者はJDIを利用して、主にユーザインターフェイス部分を実装するだけでデバッガが作れるようです。
また、JVMの実装者は、JVMTIの仕様を満たすようにJVMを実装し、JDWPとJDIに関する実装はSunのリファレンス実装を利用すれば、新しく実装したJVM上で動作するJavaプログラムのデバッグを、既存のデバッガで行うことができるんでしょう(たぶん)。
メモ
- JPDAに関するドキュメント
http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ja/guide/jpda/index.html
- Java Debugger
- CUIベース
- jdb
- jdebug
- GUIベース
- jswat
- CUIベース
- JVMの種類
- Sun JVM
- IBM JVM
- WebLogic JRockit JVM
- Microsoft JVM
*1:Java2 sdk 1.4時点