デバッガ:デバッグ環境の実例
「デバッグAPI」と「デバッグ環境」を区別する理由はどこにもありません。しいて言えばAPIがたくさんあるので単なるAPIではなく、もう少し大きな意味での「環境」という言葉を使いたかったためにこうしました。単にページを分けたかったというのもあります。
Javaのデバッグ環境
Javaのデバッグ環境には、その総称として JPDA = Java Platform Debugger Architecture と名づけられています。
Java Platform Debugger Architecture リファレンス
基本的なアーキテクチャ
JPDAは基本的に以下の三つのインターフェースから構成されています。
- JVM TI = Java Virtual Machine Tool Interface
- JavaVM自身の情報の公開や制御のためにある、JavaVMのC言語用デバッグインターフェース
- 仕様
- JDWP = Java Debug Wire Protocol
- JavaVMとデバッガとの連絡を取るために使われる通信プロトコル(TCP/IPや共有メモリなどのトランスポート機構は定義しない)
- 仕様
- JDI = Java Debug Interface
- アプリケーションのデバッグに使われるpure Javaなクラス群の総称
- 仕様
デバッギ dllやsoなどのオブジェクト デバッガ側
|--------------| |----------------| |----------------||---------------|
| | | | | || |
| JVM TIを持つ | - | バックエンド | JDWPを使った通信 | フロントエンド || JDIを利用した |
| JavaVM | | | ←-→ | (JDIを実装) || プログラム |
| | | | | || |
|--------------| |----------------| |----------------||---------------|
図示するとこのようになります。バックエンドが別のオブジェクトになっているのは
JavaVMの実装がいくつもあることや、バックエンドが常には必要ないことに由来していると思われます。
前者はバックエンドをいくつも作るのは無駄なので、共通化できるところは共通化してしまおうという話です。
また、後者の理由によりバックエンドは常に起動されるとは限らないため、Javaでデバッグされるプロセスを起動する場合にはいつも付加的なオプションを用いる必要があります。
JDIはデバッガ側からみると、デバッギプロセスのリモートビューとなります。
重要だと思われる点
関数やクラスがたくさんありすぎて正直何を書けばいいのか分かりません(^^; リファレンスを見た方が早いので必要ないかもしれませんが、一応重要だと思われる点をまとめてみます。
JVM TI
- 仕様にある「エージェント」とはJVM TIのクライアントのことで、普通はバックエンドのことを指します
- スタックフレームのポップができます。これは正常終了の場合と強制終了の場合を含みます
- スタックフレームからそのローカル変数を参照したり、スレッドごとの過去のコールスタックを取得することなどが可能です
- ブレークポイントの設定や解除を行えます。その際指定するのは「クラスのメソッドID」と「その中での位置を指定するもの」です
- クラスフィールドのアクセスや変更など監視を行えます
- クラス情報としては、名前・修飾子・ステータス(ロードが終わったかなど)・ソースファイル名・フィールドなどが取得可能です
- メソッド情報としては、名前・修飾子・行番号と対応するバイトコードの位置・バイトコード・局所変数情報などが取得可能です
- JavaVMからバックエンドへの通知はイベントと呼ばれ、関数コールバックより行われます。イベントに対応する関数をそれぞれ設定します
- イベントのフィルタリングなども行うことができます
- イベント一覧はこちらイベントの索引。以下は主要なもののみです
- ブレークポイント
- クラスのロード
- 動的コード生成
- コンパイル済みメソッドのロード/アンロード
- 例外/例外キャッチ
- フィールドアクセス/変更
- ガベージコレクションの開始/完了
- メソッドエントリ/終了
- モニター待機/待機終了
- オブジェクトの割り当て/解放
- ステップ実行
- スレッドの終了/開始
- VMの終了/初期化/終了
JDWP
- これは単なるプロトコルです。実際にどのような通信を行うかは自由となっています
- デフォルトではTCP/IPや共有メモリでの通信が用意されていますが、その他ユーザーが自由に作成することも可能です
- 通信方式を拡張する場合はJavaの com.sun.jdi.connect.spi(spiはService Provider Interfaceの略) を使いますリファレンス
- JDWPの仕様には「JDWPの設計は、簡単に実装できるよう十分に単純化されていますが、将来の拡張に対応する柔軟性もあります」とあるので何かの役に立つかもしれません。一応パケットの中身を引用しておきます
typedef struct {
jint len;
jint id;
jbyte flags;
jbyte cmdSet;
jbyte cmd;
jbyte *data;
} jdwpCmdPacket;
typedef struct {
jint len;
jint id;
jbyte flags;
jshort errorCode;
jbyte *data;
} jdwpReplyPacket;
typedef struct jdwpPacket {
union {
jdwpCmdPacket cmd;
jdwpReplyPacket reply;
} type;
} jdwpPacket;
JDI
- JavaのJavaによるJavaのためのデバッグインターフェースです
- デバッギへの通知をリクエストと呼び、com.sun.jdi.request.* で処理します
- デバッギからの通知をイベントと呼び、com.sun.jdi.event.* で処理します
- イベントの内容はJVM TIで扱ったののサブセットのような感じになっています。あまり細かいイベントは扱われていません
- コアオブジェクト群もやはり、JVM TIで扱ったオブジェクトのラッパーのような感じになっていますです。デバッギの数値や変数・メソッドなどの情報をネットワークなどを意識せずに扱うことができます
- すでに起動されているJavaVMに対してアタッチすることが可能です
Last modified : 2009/01/30 12:08:06 UTC