Java

JavaTM Platform Debugger Architecture -
サービスプロバイダインタフェース

ドキュメントの目次

J2SE 5.0 では、コネクタと TransportService の実装を開発および配置できるように、新しいサービスプロバイダインタフェースが Java Debug Interface (JDI) に追加されています。TransportService は、5.0 の新しいクラスです。このクラスは、コネクタによって使用される基盤のトランスポートサービスを表し、デバッガとターゲット VM 間の接続の確立、および Java Debug Wire Protocol (JDWP) パケットの転送に使用されます。

JDI の新しいサービスプロバイダインタフェースに加え、J2SE 5.0 には JavaTM Debug Wire Protocol Transport Interface (jdwpTransport) という新しいトランスポートライブラリインタフェースも含まれています。これは、トランスポートライブラリの開発および配置を可能にするネイティブ (C/C++) インタフェースです。トランスポートライブラリは、debuggee 側の JDWP エージェントによってロードされ、デバッガとの接続の確立、およびデバッガと VM 間の JDWP パケットのトランスポートに使用されます。

このページでは、新しいインターフェースを使用する場合のシナリオについていくつか説明します。また、新しいコネクタとトランスポートの実装の開発および配置に関連するタスクの概要も説明します。


シナリオの例

サービスプロバイダインタフェースとネイティブトランスポートインタフェースは、次のユーザーによって使用されることが想定されています。

これらのユーザーを考慮して、新しいインターフェースを使用する場合のいくつかのシナリオについて以下で説明します。


コネクタの開発

コネクタの開発には、LaunchingConnector、AttachingConnector、または ListeningConnector の固定実装が含まれます。

各コネクタの実装には、すべてのコネクタメソッドの実装のほかに、public で引数なしのコンストラクタが必要です。コンストラクタは、初期化中に VirtualMachineManager によって呼び出されます。コンストラクタは無操作の場合や、トランスポートサービスのロードなどの初期化タスクを実行する場合があります。コンストラクタは、チェックされる例外をスローしません。 このため、初期化中の問題はエラーまたはチェックされない例外としてスローされます。

コネクタで TransportService を使用する必要はありません。コネクタによっては、トランスポート以外の機構を使用してターゲット VM に接続する場合があります (シナリオの例のセクションでは、クラッシュダンプやハングプロセスに接続する AttachingConnectors の例を列挙)。TransportService 実装を使用するコネクタの場合、コネクタは TransportService 実装を直接参照するか、実行時に実装をロードすることができます。Sun が提供するトランスポートを利用するコネクタは、次のようなコードを使用してトランスポートサービスをロードする必要があります。

try {
    Class c = Class.forName("com.sun.tools.jdi.SocketTransportService");
    ts = (TransportService)c.newInstance();
} catch (Exception x) {
    throw new Error(x);
}

Java SE の実装には、Sun のソケットトランスポートサービスまたは共用メモリートランスポートサービスが含まれている必要がないため、この例では、トランスポートサービスが存在しない場合、エラーがスローされます。

コネクタのタイプが認識されていると仮定する場合、実装を開発するときに次のことに注意する必要があります。

LaunchingConnector の例のソースコードを見るには、ここをクリックしてください。コネクタには、ターゲット VM で実行するクラスのクラス名を指定する class という 1 つの Connector.Argument があります。この例では、Connector.Argument、トランスポートの命名、createVirtualMachine メソッドの使用を含む、前述のすべての要点を示しています。


コネクタの配置

コネクタを配置するには、コネクタの完全修飾クラス名のリストを含むサービス設定ファイルと一緒にコネクタ実装のクラスを jar ファイルにパッケージ化する必要があります。その後、jar ファイルはシステムクラスローダーから可視の場所に配置されます。

META-INF/services/com.sun.jdi.connect.Connector というサービス設定ファイルが jar ファイルに含まれている必要があります。 このファイルには、jar ファイルに含まれているコネクタの完全修飾クラス名のリストがあります。複数のコネクタ実装が同じ jar ファイルに含まれている場合があります。 この場合、各コネクタのクラス名は別の行に記載されます。

SimpleLaunchingConnector という起動コネクタを配置したいと仮定します。このコネクタを配置するために、次のような META-INF/services/com.sun.jdi.connect.Connector ファイルを作成します。

# Our very simple launching connector
SimpleLaunchingConnector

このサービス設定ファイルは、コネクタの実装を構成するクラスと一緒に jar ファイルにパッケージ化されます。

jar cf SimpleLaunchingConnector.jar \
    META-INF/services/com.sun.jdi.connect.Connector \
    SimpleLaunchingConnector.class

次に、jar ファイルはシステムクラスローダーから可視の場所にコピーされます。

ファイルが配置されると、デバッガの再起動時にコネクタが配置されます。つまり、VirtualMachineManager の allConnectors() メソッドによって返されるコネクタのリストに SimpleLaunchingConnector が含まれます。また、これは起動コネクタであるため、launchingConnectors() メソッドによって返される起動コネクタのリストにも表示されます。


TransportService の開発

トランスポートサービスを開発するには、次の 2 つのコンポーネントを開発する必要があります。

トランスポートサービスの開発には、トランスポートと基盤になる通信プロトコルについての高度な知識が必要です。トランスポートサービスは、JDWP を基盤となる通信プロトコルにバインドします。提供するサービスは信頼性が高く、JDWP パケットはデバッガと debuggee の間で重複したりデータが失われることなく、交換されます。パケットを信頼性の高い方法で交換しなければならないことを考えると、トランスポートサービスは、基盤となる通信プロトコルが提供するサービスを超えるプロトコルサポートを提供するべきです。たとえば、処理されていない信頼性の低いシリアル接続を介したデバッグが必要な場合、トランスポートサービスの実装者は、エラーの検出と回復を実装に組み込んで、デバッガと debuggee の間で JDWP パケットを信頼性の高い方法で転送できるようにする必要があります。

トランスポートと基盤の通信プロトコルの詳細を理解したら、次のことを考慮します。

上記の内容が解決したら、TransportService の作成によって com.sun.jdi.connect.spi.TransportService を拡張し、実装を提供します。attach メソッドと accept メソッドは、com.sun.jdi.connect.spi.Connection のインスタンスを返します。 このため、Connection を実装して、デバッガが debuggee と JDWP パケットを交換できるようにする必要があります。

TransportService 実装の例として、Sun のソケットトランスポートのソースコードを見るには、ここをクリックしてください。この例は、参照用として提供されています。

ネイティブトランスポートライブラリを開発するには、jdwpTransport 仕様に記載されている各関数を実装する必要があります。関数のプロトタイプおよび定義は、${java_home}/include/jdwpTransport.h に定義されています。

トランスポートライブラリの実装者は、ダイナミックライブラリ (またはこれに相当するもの) への関数実装のコンパイルおよびリンクを行います。ライブラリは、トランスポートライブラリがロードされるときに JDWP エージェントから呼び出される jdwpTransport_OnLoad 関数をエクスポートします。一部の組み込み環境は、動的リンクをサポートしていません。 そういった環境では、トランスポートライブラリに静的にリンクしなければならない場合があります。その場合、ライブラリのロードはありませんが、トランスポートライブラリを初期化し、環境ポインタを取得するために、jdwpTransport_OnLoad 関数が呼び出されます。

jdwpTransport 実装の例として、Sun のソケットトランスポートライブラリ (dt_socket) のソースコードを見るには、ここをクリックしてください。この例は、あくまでも参照用として提供されています。


TransportService の配置

TransportService は、コネクタと同様の方法で配置されます。TransportService を配置するには、TransportService の完全修飾クラス名のリストを含むサービス設定ファイルと一緒に TransportService 実装のクラスを jar ファイルにパッケージ化する必要があります。その後、jar ファイルはシステムクラスローダーから可視の場所に配置されます。

META-INF/services/com.sun.jdi.connect.spi.TransportService というサービス設定ファイルが jar ファイルに含まれている必要があります。 コネクタの配置と同様に、jar ファイルに複数の実装が含まれている場合は、複数のトランスポートサービス実装のクラス名が設定ファイルに記載されることがあります。

トランスポートサービス com.sun.SerialTransportService の場合、サービス設定ファイルは次のようになります。

# Serial line transport
com.foo.SerialTransportService

このサービス設定ファイルは、実装を構成するクラスと一緒に jar ファイルにパッケージ化されます。この例では、実装に多数のクラスが含まれると仮定します。

jar cf SerialTransportService.jar \
    META-INF/services/com.sun.jdi.connect.spi.TransportService \
    com/foo/SerialTransportService.class \
    com/foo/SerialConnection.class \
    com/foo/SerialCapabilities.clas \
    com/foo/SerialIO.class \
    com/foo/SerialProtocol.class 

コネクタの配置と同様に、jar ファイルはシステムクラスローダーから可視の場所にコピーされます。

TransportService は、ネイティブメソッドを使用する場合もあれば、ネイティブライブラリを必要とするほかの API に依存する場合もあります。その場合、ネイティブライブラリは、System.loadLibrary を使用してロードできる場所に存在する必要があります。

ネイティブトランスポートライブラリは、JDWP エージェントによってロードされます。このため、ネイティブトランスポートライブラリは、オペレーティングシステムの通常の実行時ライブラリ検索パス上に存在する必要があります。たとえば、Solaris または Linux システムの場合は、LD_LIBRARY_PATH 環境変数によって指定された検索パス上に存在する必要があります。


Copyright c 2004 Sun Microsystems, Inc.All Rights Reserved.

コメントの送付先: Debugging Feedback

Sun