目次 | 前の項目 | 次の項目 | Java Remote Method Invocation |
RMI ランタイム実装には、接続のために java.net.Socket および java.net.ServerSocket が必要です。RMI ランタイム実装は、これらのクラスのオブジェクトを直接初期化するのではなく、static メソッドRMISocketFactory.getSocketFactory
によって返される、現在の RMISocketFactory オブジェクトのcreateSocket
およびcreateServerSocket
メソッドを呼び出します。これにより、アプリケーションは、java.net.Socket および java.net.ServerSocket クラスの代替サブクラスなどの RMI 転送で使われるソケットの種類をカスタマイズするためのフックを保持できます。使用される RMISocketFactory のインスタンスは、信頼できるシステムコードによって一度に設定できます。JDK 1.1 では、このカスタマイズは、ソケットの種類についての全般的な設定を行う場合に限られていました。これは、ファクトリのメソッドに渡されるパラメータが、createSocket
のホストとポート、およびcreateServerSocket
のポート番号だけであったためです。JDK 1.2 では、リモートオブジェクトとの通信にどのプロトコルを使うかについて、さらに柔軟なカスタマイズを提供するため、新しいインタフェース RMIServerSocketFactory および RMIClientSocketFactory が導入されました。
RMI を使ったアプリケーションで、これらの新しいソケットファクトリインタフェースを利用するために、UnicastRemoteObject と java.rmi.activation.Activatable の両方に、いくつかの新しいコンストラクタおよび
exportObject
メソッドが追加されました。これらのコンストラクタおよびメソッドは、クライアントおよびサーバソケットファクトリを追加されたパラメータとして利用します。この新しいコンストラクタまたは
exportObject
メソッドのどちらかによって (RMIClientSocketFactory および RMIServerSocketFactory パラメータを使って) エクスポートされるリモートオブジェクトは、RMI ランタイムにより特別に扱われます。リモートオブジェクトの有効期間中、ランタイムは、ServerSocket を作成してリモートオブジェクトへの着呼を受け入れるためには、カスタムの RMIServerSocketFactory を使用し、Socket を作成してクライアントをリモートオブジェクトに接続するためには、カスタムの RMIClientSocketFactory を使用します。カスタムソケットファクトリとともにエクスポートされるリモートオブジェクトのスタブおよびスケルトン内で使われる RemoteRef および ServerRef の実装は、それぞれ UnicastRef2 および UnicastServerRef2 です。UnicastRef 型のワイヤの表現では、接続するための「エンドポイント」の表現に、UTF 形式のホスト名文字列とそのあとに整数のポート番号だけを使用していました。UnicastRef2 型のワイヤの表現には、これとは異なる表現が含まれています。UnicastRef2 では、エンドポイントのワイヤ表現は、残りのエンドポイント表現の内容を指定する形式のバイト (将来のエンドポイント表現の拡張用) 、およびそれに続く指定された形式のデータによって構成されています。現在のところ、データは、UTF 形式のホスト名、ポート番号、および (エンドポイントの形式バイトによって指定されたときは) クライアントがこのエンドポイントでリモートオブジェクトへのソケット接続を生成するために使う RMIClientSocketFactory オブジェクトの直列化表現で構成されます。エンドポイントの表現には、リモートオブジェクトのエクスポート時に指定された RMIServerSocketFactory オブジェクトは含まれません。
UnicastRef2 型の参照を使って呼び出しが行われた場合、ランタイムは、指定されたリモートオブジェクトへの接続用ソケットの作成時に、エンドポイントの RMIClientSocketFactory オブジェクトの
createSocket
メソッドを使います。また、ランタイムが特定のリモートオブジェクトに対して DGC「dirty」および「clean」呼び出しを実行する際に、リモート参照で指定されたのと同じ RMIClientSocketFactory オブジェクトから生成された接続を使って、リモート VM 上の DGC を呼び出す必要があります。サーバ側の DGC 実装は、この処理が正しく行われたことを確認する必要があります。カスタムソケットファクトリを引数としてとらない UnicastRemoteObject 上の古いコンストラクタまたはメソッドを使ってエクスポートされたリモートオブジェクトでは、以前と同様に、UnicastRef および UnicastServerRef 型の RemoteRef および ServerRef が使われます。このようなオブジェクトには、エンドポイントの古いワイヤ表現である、UTF 形式のホスト文字列に続いてポート番号を指定する整数が使われます。これは、新しい JDK 1.2 の機能を使わない RMI サーバが、以前のバージョンの RMI クライアントと相互運用を可能にするためです。
java.rmi.server.RMISocketFactory 抽象クラスは、トランスポートがソケットを取得する方法を指定するインタフェースを提供します。以下のクラスは、java.net パッケージの Socket および ServerSocket を使用します。
package java.rmi.server; public abstract class RMISocketFactory implements RMIClientSocketFactory, RMIServerSocketFactory { public abstract Socket createSocket(String host, int port) throws IOException; public abstract ServerSocket createServerSocket(int port) throws IOException; public static void setSocketFactory(RMISocketFactory fac) throws IOException; public static RMISocketFactory getSocketFactory(); public static void setFailureHandler(RMIFailureHandler fh); public static RMIFailureHandler getFailureHandler(); }
static メソッド setSocketFactory は、RMI がソケットを取得するためのソケットファクトリを設定します。アプリケーションが自身の RMISocketFactory のインスタンスのためにこのメソッドを呼び出せるのは一回だけです。アプリケーションの定義による RMISocketFactory の実装は、たとえば接続要求に対して事前にフィルタリングを行なって例外をスローするか、あるいは java.net.Socket または java.net.ServerSocket クラスを独自に拡張したものを返して、確実な通信チャネルを確保します。RMISocketFactory を設定できるのは、実行中のセキュリティマネージャがソケットファクトリの設定を許している場合だけであることに注意してください。ソケットファクトリが許可されていない場合には、SecurityException がスローされます。static メソッド getSocketFactory は、RMI によるソケットファクトリを返します。ソケットファクトリが設定されていなければ、このメソッドは null を返します。
トランスポートレイヤは、トランスポートでソケットの作成が必要になると、
getSocketFactory
メソッドが値を返した RMISocketFactory 上で createSocket と createServerSocket メソッドを呼び出します。例を示します。
RMISocketFactory.getSocketFactory().createSocket(myhost, myport)
createSocket メソッドは、指定されたホストとポートに接続されたクライアントソケットを作成するものです。createServerSocket は、指定されたポート上にサーバソケットを作成するものです。デフォルトトランスポートにおける RMISocketFactory の実装は、次のように、HTTP を使ってファイアウォールを通り抜ける透過性のある RMI を提供します。
setFailureHandler
メソッドは、サーバソケットの作成に失敗すると失敗用ハンドラを RMI ランタイムにより呼び出されるように設定します。失敗用ハンドラはブール値を返して、リトライを行なってよいかどうかを示します。デフォルトの失敗用ハンドラは false を返し、デフォルト条件ではランタイムはソケット作成のリトライを行わないことを示します。
getFailureHandler
メソッドは、ソケット作成失敗の現在のハンドラを返し、失敗用ハンドラが設定されていなければ、null を返します。
リモートオブジェクトとのカスタムの通信をサポートするには、エクスポート時にリモートオブジェクトに対して RMIServerSocketFactory のインスタンスを指定します。これは、適切な UnicastRemoteObject コンストラクタかexportObject
メソッド、または適切な java.rmi.activation.Activatable コンストラクタかexportObject
メソッドを使用して実行します。このようなサーバソケットファクトリが、リモートオブジェクトとエクスポート時に関連付けられた場合、RMI ランタイムは、リモートクライアントからの接続を受け入れるために、リモートオブジェクトのサーバソケットファクトリを使って (RMIServerSocketFactory.createServerSocket
メソッドを使用して) ServerSocket を作成します。
package java.rmi.server; public interface RMIServerSocketFactory { public java.net.ServerSocket createServerSocket(int port) throws IOException; }
リモートオブジェクトとのカスタム通信をサポートするために、エクスポート時にリモートオブジェクトの RMIClientSocketFactory のインスタンスを指定できます。これは、適切な UnicastRemoteObject コンストラクタかexportObject
メソッド、または適切な java.rmi.activation.Activatable コンストラクタかexportObject
メソッドによって行います。エクスポート時に、リモートオブジェクトにこのようなサーバソケットファクトリが関連付けられている場合、リモートオブジェクトに対するリモート参照とともにクライアントソケットファクトリがリモート Virtual Machine にダウンロードされます。RMI ランタイムは、クライアントからリモートオブジェクトへの接続に、RMIClientSocketFactory.createSocket
メソッドを使用します。
package java.rmi.server; public interface RMIClientSocketFactory { public java.net.Socket createSocket(String host, int port) throws IOException; }