JavaTM Platform Debugger Architecture |
ホームページ |
JVMDI のモジュール性
Java Virtual Machine Debug Interface (JVMDI) では、仮想マシン (VM) で動作する Java プログラミング言語のアプリケーションをデバッグできるようにするため、その VM から提供される機能について記述されています。 JPDA では、JVMDI は VM によって実装され、クライアントは JPDA のバックエンドになります。 JPDA のリファレンス実装では、JVMDI は Java HotSpot VM によって実装され、クライアントはバックエンドのリファレンス実装 (Java 2 SDK, Standard Edition に付属の、jdwp.so や jdwp.dll などのネイティブ共用ライブラリとして提供される) になります。
Java HotSpot VM 以外の多くの VM も、JVMDI を実装しています。 バックエンドのリファレンス実装は、ほかのいくつかのプラットフォームに移植されました。 さらに、バックエンド以外にも JVMDI のクライアントがあります。最も有名なのは、ネイティブコードと Java プログラミング言語コードの両方のデバッグを可能にするアプリケーションエージェント (ネイティブレベルの制御と情報を必要とする) です。 バックエンドのクリーンルーム実装を意識する必要はありません。そのようなバックエンドを作成することも可能ですが、相当な労力を必要とします。
一部の VM では、JVMDI の実装に問題があります。 そのような VM では、JDWP が直接実装されます。 クライアント側では、Java プログラミング言語で作成されていないアプリケーションは、JDI を使用するアプリケーションとして不適格なことがあります。 アプリケーションによっては、JDWP のクライアントとして実装することもあります。
JDI は、アプリケーションの静的なビューを提供するようにシステムによって実装されることがあります。 また、JDWP のフロントエンドとはまったく違う機構で情報を収集したり VM を制御したりするように実装されることもあります。
動作の概要
これまでは、各インタフェースを使用するさまざまな方法について説明してきました。 このあとは、標準的な JPDA が全体としてどのように動作するかを見ていきます。 説明の中では、個々の呼び出しやコードの詳細について、実例を取り上げます。 そのような実例は、理解できなくても問題ありません。実例を具体的にするために紹介してあるだけだからです。
各インタフェースを橋渡しするのは、 要求とイベントという 2 つのアクティビティです。 要求は、デバッガ側から出されるもので、情報の照会、リモート側の VM やアプリケーションの状態変更の設定、およびデバッグ状態の設定が含まれています。 イベントは、debuggee 側から出されるもので、リモート側の VM やアプリケーションの状態変化を示しています。
1 つの実例を調べてみましょう。 IDE のスタック表示でユーザが局所変数をクリックし、その値を要求したとします。 IDE は、JDI を使ってその値を取得します。具体的には、getValue
メソッドを呼び出します。次に例を示します。
theStackFrame.getValue(theLocalVariable)ここで、
theStackFrame
は com.sun.jdi.StackFrame
であり、theLocalVariable
は com.sun.jdi.LocalVariable
です。
次に、フロントエンドは、この要求を通信チャネル (たとえば、ソケット) 経由で、debuggee プロセスが動作しているバックエンドに送ります。 そのとき、フロントエンドは、その要求を JDWP に準拠したバイトストリームの形式に変換します。 具体的に言うと、フロントエンドは GetValues コマンド (バイト値 1) を StackFrame コマンドセット (バイト値 16) で送り、 そのあとにスレッド ID、フレーム ID などが続きます。
バックエンドは、そのバイトストリームを解析し、JVMDI を介して VM に照会を送ります。 具体的には、要求された値が整数だとすると、次のような JVMDI 関数の呼び出しを実行します。
error = jvmdi->GetLocalInt(frame, slot, &intValue);バックエンドは、ソケット経由で応答パケットを返送します。そのパケットには
intValue
の値が入っており、JDWP に準拠したデータ形式になっています。 フロントエンドは、応答パケットを解析し、その値を getValue
メソッド呼び出しの値として返します。 最後に、IDE は、返された値を表示します。
デバッグ状態を変更する要求も、同様の方法で処理されます。 たとえば、ブレークポイントを設定するという要求は、同様のステップで処理されます。もちろん、呼び出される JDI メソッドや、送信される JDWP コマンドや、呼び出される JVMDI 関数は違います。 さらに、フロントエンドとバックエンドは、単にデータをやり取りする以上のことを行います。アクティビティを追跡およびスケジューリングし、情報を変換、フィルタリング、およびキャッシュします。したがって、ブレークポイントを設定する要求は、値を取得する照会とはかなり違った仕方で処理されますが、通信の手順は同じです。
デバッグしているアプリケーションがこのブレークポイントに達すると、何が起こるのでしょうか。 今度は、イベントの出番になります。 仮想マシンは、JVMDI インタフェースを介してイベントを送ります。 具体的には、仮想マシンは、イベント処理関数を呼び出して、ブレークポイントのイベント構造体を渡します。
typedef struct { jthread thread; jclass clazz; jmethodID method; jlocation location; } JVMDI_breakpoint_event_data;バックエンドは、イベント処理関数を次のように設定しています。
static void eventHook(JNIEnv *env, JVMDI_Event *event) { ...このバックエンド関数は、関心のあるイベントをフィルタリングし、そのイベントをキューに入れ、ブレークポイントイベント用に定義された JDWP 形式のソケットを介してそのイベントを送信するという、一連のアクティビティを開始します。 フロントエンドは、そのイベントをデコードして処理し、最終的には JDI イベントを生成します。 具体的には、JDI イベントは、
com.sun.tools.jdi.event.BreakpointEvent
として公開されます。 その後、IDE は、そのイベントをイベントキューから取り出して取得します。 theEventQueue.remove()ここで、
theEventQueue
は、com.sun.jdi.event.EventQueue
です。 IDE は、JDI を介して多くの照会呼び出しを実行することにより、表示を更新すると予想されます。
移殖
仮想マシンの各実装には、それぞれ独自の JVMDI 実装が必要です。JVMDI の実装では、VM のデータ構造に深く踏み込む必要があり、イベントを取得するために VM 実装の中にフックを設定する必要があります。 JVMDI サポートのない VM に JVMDI を追加するのは、かなりの作業になります。 VM の複雑さと、実装する JVMDI のオプション機能の量に応じて、3 〜 12 か月の作業になると考えられます。 JVMDI サポートが組み込まれている VM を新しいプラットフォームに移殖する作業は、VM の JVMDI 以外の部分の移殖が中心になります。JVMDI 部分に必要な付加的な作業量は、比較的少ないものです。
バックエンドのリファレンス実装を新しいプラットフォームに移すには、多くの場合、ソースにわずかの変更 (数行のみ) を加えるか、ソースをまったく変更せずに、再コンパイルするだけで済みます。 同じプラットフォーム上で新しい VM を使用する場合は、バックエンドのバイナリコードは多くの場合そのまま動作します。ただし、それは Java プログラミング言語のコードではないため、内容を理解することはできません。 このドキュメントではライセンスの問題には触れていないので、注意してください。
フロントエンドの実装は Java プログラミング言語で作成されているため、どのプラットフォームまたは VM でも動作します。 ただし、一部のシステムでは、コネクタコードの機能の一部を拡張する必要がある場合もあります。 たとえば、フロントエンドのリファレンス実装に含まれている起動ツールでは、仮想マシンが J2SE の規則を使って起動されることを前提としています。 JDI のユーザが自分たちの希望に合わせて起動ツールの構文を決めることもできますが、一般に、デバッガアプリケーションでは、その構文が JDI 実装の側で決められていると想定します。 また、もし別の種類の通信チャネル (たとえば、シリアル接続) が必要な場合は、その機能も追加する必要があります。 結局、その追加を可能にするには、JDI に SPI を追加することになります。 ただし、現在のところ、それにはソースを変更する必要があります。
Copyright © 2001 Sun Microsystems, Inc. All Rights Reserved.
コメントの送付先: java-debugger@java.sun.com |