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

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

JDI の新しいサービスプロバイダインタフェースに加え、J2SE 5.0 には Java™ 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 © 1993, 2013, Oracle and/or its affiliates. All rights reserved.