Java Debug Interface (JDI)のサービス・プロバイダ・インタフェースを使用すると、Connector
とTransportService
の実装を開発および配備できます。 TransportService
クラスは、Connector
で使用される基盤のトランスポート・サービスを表し、デバッガとターゲットVM間の接続の確立、およびJava Debug Wire Protocol (JDWP)パケットのトランスポートに使用されます。
JDIのサービス・プロバイダ・インタフェースに加えて、JDKにはJava Debug Wire Protocol Transport Interface (jdwpTransport)と呼ばれるトランスポート・ライブラリ・インタフェースも含まれています。 これは、トランスポート・ライブラリの開発および配置を可能にするネイティブ(C/C++)インタフェースです。 トランスポート・ライブラリは、debuggee側のJDWPエージェントによってロードされ、デバッガへの接続の確立、およびデバッガとVM間のJDWPパケットのトランスポートに使用されます。
このページでは、新しいインタフェースが使用される可能性のあるいくつかのシナリオについて説明します。 また、新しいコネクタとトランスポートの実装の開発および配置に関連するタスクの概要についても説明します。
サービス・プロバイダ・インタフェースとネイティブ・トランスポート・インタフェースは、次のユーザーによって使用されることが想定されています。
LaunchingConnector
実装を開発する必要がある、またはOracleが提供するTCP/IPおよび共用メモリー・トランスポートを越えるリモート・デバッグ用トランスポート・オプションを追加するデバッガおよびツールのベンダー。これらのユーザーを考慮して、新しいインタフェースを使用する場合のいくつかのシナリオについて説明します。
多くの環境、特に組込みデバイスでは、TCP/IP以外のトランスポートを使用してデバッガをターゲットVMに接続することが必要になる場合があります。 このタイプの環境では、別のトランスポートを開発したり、別のトランスポートを介したデバッグをサポートしたりするために新しいサービス・プロバイダ・インタフェースを使用できます。
debuggee側では、jdwpTransportインタフェースを実装することにより、新しいトランスポートのトランスポート・ライブラリを開発できます。 デバッガの場合は、TransportService実装を開発できます。 TransportService実装を配置すると、JDI VirtualMachineManager実装によって自動的にAttachingConnectorおよびListeningConnectorが作成され、ターゲットVMに対するリモート・デバッグが可能になります。
環境によっては、トランスポート以外のメカニズムを使用してデバッガをターゲットVMに接続することが必要になる場合があります。 たとえば、クラッシュ・ダンプまたはハング・プロセスに(読取り専用で)接続するためにデバッガが使用される場合があります。
これらの例の場合は、AttachingConnector
実装を開発できます。 AttachingConnector
実装は、com.sun.jdi.connect.AttachingConnectors
を拡張し、配備されると、VirtualMachineManagerのattachingConnectors()
メソッドによって返される接続コネクタのリストに表示されます。
com.sun.jdi.CommandLineLaunch
LaunchingConnector
によって使用されるConnector引数または起動メカニズムが十分でない場合があります。 この場合、オペレーティング・システムまたは仮想マシンのベンダーが、ターゲットVMを起動できる独自のLaunchingConnector
を開発することがあります。 この新しいLaunchingConnector
は、デバッグするターゲットVMの構成に使用される適切なConnector
引数を持ちます。 これを配備すると、VirtualMachineManager
オブジェクトのlaunchingConnectors()
メソッドによって返されるConnectors
のリストに表示されます。 別の例は、Integrated Development Environment (IDE)の実装者がOracle以外のトランスポートでのデバッグをサポートする場合の企業環境において発生します。 たとえば、TLS/SSLを使用するセキュアな接続を介したデバッグのオプションをIDEで提供する場合があります。
この例では、IDEの実装者がjdwpTransportインタフェースを使用してトランスポート・ライブラリを開発します。 この結果、debuggeeでは新しいトランスポートの使用が可能になります。 デバッガ側では、IDEの実装者に選択肢があります。 1つのオプションは、TransportService実装を開発および配置することです。 このオプションでは、リモート・デバッグに新しいトランスポートを使用できます。
あるいは、IDEの実装者が、トランスポートをカプセル化するConnector実装を作成することを決定する可能性があります。 このオプションは、IDEの実装者が新しいConnector引数を追加するときに適しています。 たとえば、セキュリティ保護されたトランスポートを使う場合、IDEの実装者が、セキュアな接続を構成するために必要なキーストア、パスフレーズなどのオプションを指定するConnector引数を持つConnectorを使用する場合があります。 新しいConnectorが適している場合、IDEの実装者は、デバッグ対象側のトランスポート・ライブラリとデバッガ側のConnectorを開発します。 Connectorのタイプは、実装者が選択できます。1つの例として、デバッグ対象を起動し、デバッガとデバッグ対象の間のセキュアな接続を確立するLaunchingConnectorがあります。
Connector
の開発には、LaunchingConnector
、AttachingConnector
、またはListeningConnector
の固定実装が含まれます。
どのConnector
実装にも、すべてのConnector
メソッドの実装の他に、publicで引数なしのコンストラクタが必要です。 コンストラクタは、初期化中にVirtualMachineManager
によって呼び出されます。 コンストラクタは無操作の場合や、トランスポート・サービスのロードなどの初期化タスクを実行する場合があります。 コンストラクタはチェック例外をスローしないため、初期化中の問題はすべて、エラー
またはその他の非チェック例外としてスローされるべきです。
Connector
でTransportService
を使用する必要はありません。 Connector
によっては、トランスポート以外のメカニズムを使用してターゲットVMに接続する場合があります(シナリオの例のセクションでは、クラッシュ・ダンプやハング・プロセスに接続するAttachingConnectors
の例を示しています)。 TransportService
実装を使用するConnector
の場合、Connector
はTransportService
実装を直接参照するか、実行時に実装をロードできます。 Oracleが提供するトランスポートを使用しようとするConnectorは、次のようなコードを使用してトランスポート・サービスをロードするようにしてください。
try {
Class<?> c = Class.forName("com.sun.tools.jdi.SocketTransportService");
ts = (TransportService)c.newInstance();
} catch (Exception x) {
throw new Error(x);
}
Java SEの実装には、Oracleのソケット・トランスポート・サービスまたは共用メモリー・トランスポート・サービスが含まれている必要がないため、この例では、トランスポート・サービスが存在しない場合、エラー
がスローされます。
Connector
のタイプが認識されていると仮定する場合、実装を開発するときに次のことに注意する必要があります。
Connector.Arguments
のリストを慎重に考慮するようにしてください。 Connector
実装によっては、デフォルト引数の構築や解析が、実装におけるコードの大部分になる場合があります。 Connector
は、自身が使用するトランスポートに名前を付ける必要があります。 実装で既存のTransportService
を使用する場合、推奨されるトランスポート名は基盤となるTransportService
の名前です。 つまり、Connector
のtransport()
実装は、name()
メソッドがトランスポートの名前を表すjava.lang.String
を返す対象となるTransport
を返します。 Connector
実装は、ターゲットVMへのConnection
を確立します。 接続が確立されると、Connector
のlaunch
、attach
、またはaccept
メソッドは、デバッガに対してVirtualMachine
インスタンスを返します。 VirtualMachine
ミラーの作成を容易にするために、VirtualMachineManager
にはVirtualMachine
を作成するメソッドが含まれています。 次のコードは、このメソッドの使用例を示しています:VirtualMachine vm = Bootstrap.virtualMachineManager().createVirtualMachine(conn);
VirtualMachineManager
には、LaunchingConnector
インスタンスが使用する別の形式のcreateVirtualMachine
メソッドも含まれています。 別の形式では、LaunchingConnector
でデバッグ対象を表すjava.lang.Process
を指定できます。 詳細は、com.sun.jdi.VirtualMachineManager
の仕様を参照してください。 Connector
を配備するには、Connector
の完全修飾クラス名のリストを含むサービス構成ファイルと一緒にConnector
実装のクラスをjarファイルにパッケージ化する必要があります。 その後、jarファイルはシステム・クラス・ローダーから可視の場所に配置されます。
META-INF/services/com.sun.jdi.connect.Connector
というサービス構成ファイルがjarファイルに含まれている必要があります。 このファイルには、jarファイルに含まれているConnector
の完全修飾クラス名のリストがあるだけです。 複数のConnector
実装が同じjarファイルに含まれている場合があります。この場合、各Connector
のクラス名は別の行に記載されます。
SimpleLaunchingConnector
という起動コネクタを配備すると仮定します。 このコネクタを配備するために、次のようなMETA-INF/services/com.sun.jdi.connect.Connector
ファイルを作成します。
# A very simple launching connector
SimpleLaunchingConnector
このサービス構成ファイルは、コネクタの実装を構成するクラスと一緒にjarファイルにパッケージ化されます。
jar cf SimpleLaunchingConnector.jar \\
META-INF/services/com.sun.jdi.connect.Connector \\
SimpleLaunchingConnector.class
次に、jarファイルはシステム・クラス・ローダーから可視の場所にコピーされます。
ファイルが配備されると、デバッガの再起動時にConnector
が配備されます。 つまり、VirtualMachineManager
のallConnectors()
メソッドによって返されるConnector
のリストにSimpleLaunchingConnector
が含まれます。 また、これは起動コネクタであるため、launchingConnectors()
メソッドによって返される起動コネクタのリストにも表示されます。
トランスポート・サービスを開発するには、次の2つのコンポーネントを開発する必要があります。
com.sun.jdi.connect.spi.TransportService
の固定実装。jdwpTransport
インタフェースを実装するデバッグ対象側の共有ライブラリ。トランスポート・サービスの開発には、トランスポートと基盤になる通信プロトコルについての高度な知識が必要です。 トランスポート・サービスは、JDWPを基盤となる通信プロトコルにバインドします。 提供するサービスは信頼性が高く、JDWPパケットはデバッガとdebuggeeの間で重複したりデータが失われることなく、交換されます。 パケットを信頼性の高い方法で交換しなければならないことを考えると、トランスポート・サービスは、基盤となる通信プロトコルが提供するサービスを超えるプロトコル・サポートを提供するべきです。 たとえば、処理されていない信頼性の低いシリアル接続を介したデバッグが必要な場合、トランスポート・サービスの実装者は、エラーの検出と回復を実装に組み込んで、デバッガとdebuggeeの間でJDWPパケットを信頼性の高い方法で転送できるようにする必要があります。
トランスポートと基盤の通信プロトコルの詳細を理解したら、次のことを考慮します。
TransportService
のcapabilities()
メソッドは、トランスポート・サービスの機能を示すTransportService.Capabilities
を返します。 したがって、トランスポート・サービスの実装者は、次のことを考慮する必要があります。
jdwpTransport_OnLoad
関数を呼び出すたびに新しい環境ポインタが返されます。 トランスポートが1つの環境のみをサポートする場合、jdwpTransport_OnLoad
の2回目以降の呼出しはエラーが返されます。 したがって、トランスポート・ライブラリの実装者は、ライブラリの実装が1つの環境または複数の環境のどちらをサポートするかを決定する必要があります。 文字列
で表現されます。 したがって、実装者はアドレスのすべてのコンポーネントを文字列
にエンコードできるように、アドレス・スキームを作成する必要があります。 たとえば、シリアル・ポートのアドレスと構成は、次のようにエンコードされます。 /dev/ttya;9600,1
ListenKey
実装を設計します。 TransportService
は、複数の異なるアドレスで同時に待機するために使用されることがあるので、各リスナーを一意に識別するために待機キーが使用されます。 TransportService
の適切な名前と説明を決定します。 起動時に、VirtualMachineManager
は接続コネクタと待機コネクタを作成して、トランスポート・サービスをカプセル化します。 これらのConnector
の名前と説明は、トランスポート・サービスの名前と説明が基準になります。たとえば、TransportService
のname()
メソッドがSerialを返す場合、VirtualMachineManager
によって作成されるConnector
は、SerialAttachとSerialListenという名前になります。 上記の内容が解決したら、TransportService
の作成によってcom.sun.jdi.connect.spi.TransportService
を拡張し、実装を提供します。 attachメソッドとacceptメソッドは、com.sun.jdi.connect.spi.Connection
のインスタンスを返します。このため、Connection
を実装して、デバッガがデバッグ対象とJDWPパケットを交換できるようにする必要があります。
ネイティブ・トランスポート・ライブラリを開発するには、jdwpTransport仕様に記載されている各関数を実装する必要があります。 関数のプロトタイプおよび定義は、${java_home}/include/jdwpTransport.h
に定義されています。
トランスポート・ライブラリの実装者は、関数実装をコンパイルし、ダイナミック・ライブラリ(またはこれに相当するもの)にリンクします。 ライブラリは、トランスポート・ライブラリがロードされるときにJDWPエージェントから呼び出されるjdwpTransport_OnLoad
関数をエクスポートします。 一部の組込み環境は、動的リンクをサポートしていません。そういった環境では、トランスポート・ライブラリに静的にリンクしなければならない場合があります。 その場合、ライブラリのロードはありませんが、トランスポート・ライブラリを初期化し、環境ポインタを取得するために、jdwpTransport_OnLoad
関数が引き続き呼び出されます。
TransportService
は、Connector
と同様の方法で配備されます。 TransportService
を配備するには、TransportService
の完全修飾クラス名のリストを含むサービス構成ファイルと一緒にTransportService
実装のクラスをjarファイルにパッケージ化する必要があります。 その後、jarファイルはシステム・クラス・ローダーから可視の場所に配置されます。
META-INF/services/com.sun.jdi.connect.spi.TransportService
というサービス構成ファイルがjarファイルに含まれている必要があります。 Connector
の配備と同様に、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
Connector
の配備と同様に、jarファイルはシステム・クラス・ローダーから可視の場所にコピーされます。
TransportService
は、ネイティブ・メソッドを使用する場合もあれば、ネイティブ・ライブラリを必要とする他のAPIに依存する場合もあります。 その場合、ネイティブ・ライブラリは、System.loadLibrary
を使用してロードできる場所に存在する必要があります。
ネイティブ・トランスポート・ライブラリは、JDWPエージェントによってロードされます。 このため、ネイティブ・トランスポート・ライブラリは、オペレーティング・システムの通常の実行時ライブラリ検索パス上に存在する必要があります。 たとえば、SolarisまたはLinuxシステムの場合は、LD_LIBRARY_PATH
環境変数によって指定された検索パス上に存在する必要があります。
Copyright © 1993, 2017, Oracle and/or its affiliates. All rights reserved.