Java

JavaTM Debug Wire Protocol

プロトコルの詳細

概要

Java TM Debug Wire Protocol (JDWP) は、デバッガと JDWP がデバッグする Java Virtual Machine (VM) 間の通信に使用されるプロトコルです。 以降、JDWP がデバッグする VM をターゲット VM と呼びます。JDWP が存在することにより、同一のデバッガが次の状況で動作するようになります。

将来のバージョンの JDWP では、インプロセスデバッギングが可能になる予定です。

JDWP は、多くのプロトコル仕様とは、詳細フォーマットおよびレイアウト面で異なりますが、トランスポート面では異なりません。JDWP 実装は、単純な API を使用して、異なるトランスポート機構を受け付けるように設計することが可能です。特定のトランスポートが、上記の 3 つのデバッガ/ターゲット VM の各組み合わせを必ずしもサポートする必要はありません。

JDWP の設計は、各実装に対応するものとして十分単純化されていますが、将来の拡張に対応する柔軟性もあります。

JDWP は、JDI API を使って効率的に使用できることを主眼に設計されています。 その機能の多くはこの目的に沿って編成されます。

JDWP は、デバッガおよびターゲット VM を範囲として実装されます。一般に、デバッガ側は Java で記述され、ターゲット側はネイティブコードで記述されます。ターゲット側をネイティブコードで記述するのは、Java 言語実装で避けることのできないデッドロックおよび侵入を避けるためです。

現在のところ、JDWP はトランスポートランデブー用の機構またはディレクトリサービスを一切指定しません。これは将来変更される可能性がありますが、その点は別のドキュメントで扱われることになるでしょう。

JDWP パケット

JDWP はパケットベースであり、安定していません。 基本的なパケットタイプには、 コマンドパケットと応答パケットの 2 種類があります。

コマンドパケットは、デバッガまたはターゲット VM のいずれかにより送信されます。コマンドパケットは、ターゲット VM からの情報を要求するため、またはプログラムの実行を制御するためにデバッガにより使用されます。デバッガにターゲット VM 内のイベント (ブレークポイントや例外など) を通知するために、ターゲット VM がコマンドパケットを送信します。

応答パケットは、コマンドパケットへ応答する場合にのみ送信され、コマンドの成功または失敗に関する情報を常に提供します。応答パケットは、コマンド内で要求されたデータ (フィールドまたは変数の値など) を運ぶこともあります。現在のところ、ターゲット VM から送信されるイベントは、デバッガからの応答パケットを必要としません。

JDWP は非同期です。 このため、最初の応答パケットを受信する前に、複数のコマンドパケットが送信される場合があります。

コマンドおよび応答パケットヘッダは、同じサイズになります。 これは、トランスポートの実装および抽象化を容易にするためです。各パケットのレイアウトは、次のようになります。

コマンドパケット
応答パケット

JDWP 経由で送信されるすべてのフィールドおよびデータは、ビッグエンディアン形式である必要があります。ビッグエンディアンの定義については、Java Virtual Machine 仕様を参照してください。最初の 3 つのフィールドは、両方のパケットタイプで同一です。

コマンドおよび応答パケットフィールド

共有ヘッダフィールド
length
length フィールドは、パケット全体のサイズ (length フィールドを含む) をバイトで表します。ヘッダサイズは 11 バイトです。 このため、データを含まないパケットはこのフィールドを 11 に設定します。
id
id フィールドは、各パケットコマンド/応答のペアを一意に識別するために使用されます。応答パケットは、その応答対象であるコマンドパケットと同じ id を保持します。このため、非同期のコマンドおよび応答でも一致が可能になります。id フィールドは、1 つのソースから送信される未処理のコマンドすべてで一意でなければなりません。デバッガに由来する未処理コマンドは、ターゲット VM に由来する未処理コマンドと同じ id を使用できます。これ以外には id の割り当てに関する要求事項はありません。

単純で単調なカウンタは、大半の実装に適合するはずです。そのようなカウンタは、2^32 の一意な未処理パケットが存在可能で、もっとも単純な実装の代替手段となります。

flags
flags は、コマンドをキューに入れて処理する方法を変更するため、およびターゲット VM に由来するコマンドパケットをタグ付けするために使用します。現在のところ 1 フラグビットが定義されています。将来のプロトコルでは、フラグがさらに定義される可能性があります。

0x80
応答パケット

応答ビットが設定されると、そのパケットが応答であることを示します。

コマンドパケットヘッダフィールド
command set
このフィールドは、有意義な方法でコマンドをグループ化する手段として有用です。Sun が定義したコマンドセットは、JDI でサポートされるインタフェースでコマンドをグループ化する場合に使用します。たとえば、JDI VirtualMachine インタフェースをサポートするすべてのコマンドは、VirtualMachine コマンドセット内でグループ化されます。

コマンドセット空間は、次のように大きく分けられます。

0 - 63
ターゲット VM に送信されるコマンドセット
64 - 127
デバッガに送信されるコマンドセット
128 - 256
ベンダーにより定義されたコマンドおよび拡張機能
command
このフィールドは、コマンドセット内の特定のコマンドを識別します。このフィールドは、コマンドセットフィールドと共に、コマンドパケットの処理方法を示すのに使用されます。つまり、受信側に何をすべきかを告げます。特定のコマンドについては、このドキュメント内で後述します。
応答パケットヘッダフィールド
error code
このフィールドは、応答処理中のコマンドパケットの処理が成功したかどうかを示すのに使用します。値がゼロの場合は成功を、ゼロ以外の場合はエラーを示します。返されるエラーコードは、各コマンドセット/コマンドに固有の場合がありますが、多くの場合 JVMDI エラーコードにマッピングされます。
データ
データフィールドは、各コマンドセット/コマンドに一意です。これは、コマンドパケットと応答パケットのペア間で異なります。たとえば、フィールド値を要求するコマンドパケットには、オブジェクトへの参照、およびデータフィールド内の目的の値のフィールド ID が含まれます。応答パケットのデータフィールドには、フィールドの値が含まれます。

コマンドの詳細情報

一般に、コマンドまたは応答パケットのデータフィールドは、コマンドまたは応答データを定義する複数フィールドのグループを抽象化したものです。データフィールドの各サブフィールドは、ビッグエンディアン (Java) 形式で符号化されます。各コマンドとその応答用のデータフィールド作成方法の詳細は、このセクションで説明します。

異なる JDWP コマンドおよび応答の多くに共通な、一般データ型の小規模なセットが存在します。これらについては、以下で説明します。

名前 サイズ 解説
byte 1 バイト バイト値
boolean 1 バイト ブール値。 false の場合は 0、true の場合はゼロ以外の値で符号化されます。
int 4 バイト 4 バイトの整数値。整数は、符号なしと明示されている場合を除き、符号付きです。
long 8 バイト 8 バイトの整数値。値は、符号なしと明示されている場合を除き、符号付きです。
objectID ターゲット VM 固有。 8 バイトまで (以下を参照) ターゲット VM 内のオブジェクトを一意に識別します。特定のオブジェクトは、JDWP コマンドおよび応答内の 1 つの objectID により、その存続期間内は (または、objectID が明示的に廃棄されるまで) 厳密に識別されます。ObjectID は、それが明示的に廃棄されない限り、参照されたオブジェクトがガベージコレクトされたかどうかにかかわらず、異なるオブジェクトの識別に再利用されることはありません。objectID が 0 の場合、null オブジェクトを意味します。

object ID の存在により、オブジェクトのガベージコレクションが妨げられることはありません。ガベージコレクトされたオブジェクトへ、そのオブジェクト ID を使ってアクセスしようとすると、INVALID_OBJECT エラーコードが生成されます。ガベージコレクションは、DisableCollection コマンドを使って無効にできますが、通常その必要はありません。

tagged-objectID objectID のサイズ + 1 バイト 最初のバイトは、オブジェクト型の識別用の符号バイトです。このバイトに設定可能な値については、JDWP.Tag を参照してください。 使用できるのは、プリミティブタグではなく、オブジェクトタグだけです。その直後に、objectID 本体が続きます。
threadID objectID と同じ スレッドとして認識されるターゲット VM 内のオブジェクトを一意に識別します。
threadGroupID objectID と同じ スレッドグループとして認識されるターゲット VM 内のオブジェクトを一意に識別します。
stringID objectID と同じ 文字列オブジェクトとして認識されるターゲット VM 内のオブジェクトを一意に識別します。注:これは実際には文字列ではなく、値です。
classLoaderID objectID と同じ クラスローダオブジェクトとして認識されるターゲット VM 内のオブジェクトを一意に識別します。
classObjectID objectID と同じ クラスオブジェクトとして認識されるターゲット VM 内のオブジェクトを一意に識別します。
referenceTypeID objectID と同じ ターゲット VM 内の参照型を一意に識別します。特定のクラスで、classObjectIDreferenceTypeID が同一であると想定することはできません。特定の参照型は、JDWP コマンドおよび応答内の 1 つの ID により、その存続期間内は厳密に識別されます。referenceTypeID は、参照されたクラスが読み込み解除されたかどうかにかかわらず、異なる参照型を識別するために再利用されることはありません。
classID referenceTypeID と同じ クラス型として認識されるターゲット VM 内の参照型を一意に識別します。
interfaceID referenceTypeID と同じ インタフェース型として認識されるターゲット VM 内の参照型を一意に識別します。
arrayID referenceTypeID と同じ 配列型として認識されるターゲット VM 内の参照型を一意に識別します。
methodID ターゲット VM 固有。 8 バイトまで (以下を参照) ターゲット VM 内のあるクラスのメソッドを一意に識別します。methodID は、クラス/インタフェース内のメソッド、またはそのサブクラス/サブインタフェース/実装者のいずれかを一意に識別する必要があります。methodID は、必ずしも一意である必要はありません。 これは、常に referenceTypeID とペアで 1 つのメソッドを一意に識別します。referenceTypeID は、メソッドの宣言型またはサブタイプを識別できます。
fieldID ターゲット VM 固有。 8 バイトまで (以下を参照) ターゲット VM 内のあるクラスのフィールドを一意に識別します。methodID は、クラス/インタフェース内のメソッド、またはそのサブクラス/サブインタフェース/実装者のいずれかを一意に識別する必要があります。fieldID は、必ずしも一意である必要はありません。 これは、常に referenceTypeID とペアで 1 つのフィールドを一意に識別します。referenceTypeID は、フィールドの宣言型またはサブタイプを識別できます。
frameID ターゲット VM 固有。 8 バイトまで (以下を参照) ターゲット VM 内のフレームを一意に識別します。frameID は、VM 全体 (指定されたフレーム内だけではなく) のフレームを一意に識別する必要があります。frameID は、スレッドの中断中だけ有効である必要があります。
location ターゲット VM 固有 実行可能ファイルの位置。位置は、1 バイトのタイプタグ + classID + methodID + 符号なしの 8 バイトインデックス (メソッド内の位置を識別する) により識別されます。インデックス値には、次の制限があります。
  • メソッド開始位置のインデックスは、メソッド内の他のすべての位置よりも小さい
  • メソッド終了位置のインデックスは、メソッド内の他のすべての位置よりも大きい
  • メソッドの行番号テーブルが存在する場合、特定の行に属する位置は、テーブル内のその行の位置インデックスと次の行の位置インデックスとの間になる
メソッド内のインデックス値は、メソッド内の最初の実行可能ポイントから最後まで一定に増加します。多くの実装において、メソッド内の各バイトコード命令は独自のインデックスを保持しますが、必須ではありません。

タイプタグは、位置の classID がクラスまたはインタフェースを識別するかどうかを識別する必要があります。ほとんどすべての位置はクラス内に存在しますが、インタフェースの静的初期化子内に実行可能コードを保持することも可能です。

string 可変 UTF-8 で符号化された文字列。 ゼロで終了することはなく、その前に 4 バイトの整数が付きます。
可変 ターゲット VM から取得した値。最初のバイトは、型の識別用の符号バイトです。このバイトに指定可能な値については、JDWP.Tag を参照してください。その直後に、値が続きます。この値は、objectID (ID サイズの取得を参照) またはプリミティブ値 (1 〜 8 バイト) になります。各値型の詳細については、次の表を参照してください。
untagged-value 可変 上述のように、符号バイトなしの value。この書式は、符号情報をコンテキストから判別可能な場合に使用します。
arrayregion 可変 配列操作で使用される値の簡潔な表現。最初のバイトは、型の識別用の符号バイトです。このバイトに指定可能な値については、JDWP.Tag を参照してください。 次は、シーケンス内の値の数を示す 4 バイトの整数です。 その直後に、値自体が続きます。 プリミティブ値は untagged-values のシーケンスとして符号化されます。オブジェクト値は values のシーケンスとして符号化されます。

オブジェクト ID、参照型 ID、フィールド ID、メソッド ID、およびフレーム ID は、ターゲット VM 実装が異なると、サイズも異なります。一般に、そのサイズは、JNI および JVMDI 呼び出し内の項目で使用されるネイティブ識別子のサイズに対応しています。各型の最大サイズは、8 バイトです。VirtualMachine コマンドセットの IDSizes コマンドは、これらの各型のサイズを決定するのにデバッガにより使用されます。

プロトコルの詳細


Copyright © 1999 Sun Microsystems, Inc. All Rights Reserved. 

コメントの送付先:java-debugger@java.sun.com

Sun