目次|前|次 | Java Remote Method Invocation |
java.net.Socket
およびjava.net.ServerSocket
が必要です。RMIランタイム実装は、これらのクラスのオブジェクトを直接インスタンス化するのではなく、staticメソッドRMISocketFactory.getSocketFactory
によって返される、現在のRMISocketFactory
オブジェクトのcreateSocket
およびcreateServerSocket
メソッドを呼び出します。これにより、アプリケーションは、RMI転送で使われるソケットの種類(java.net.Socket
およびjava.net.ServerSocket
クラスの代替サブクラスなど)をカスタマイズするためのフックを保持できます。使用されるRMISocketFactory
のインスタンスは、信頼できるシステム・コードによって一度設定できます。JDK1.1では、このカスタマイズは、ソケットの種類についての全般的な設定を行う場合に限られていました。これは、ファクトリのメソッドに渡されるパラメータが、createSocket
のhost
とport
、およびcreateServerSocket
のport
のみであったためです。
Java SEプラットフォームでは、リモート・オブジェクトとの通信にどのプロトコルを使うかについて、より柔軟にカスタマイズできるようにするため、新しいインタフェース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
オブジェクトから生成された接続を使用して、リモートJVM上のDGCを呼び出す必要があります。サーバー側のDGC実装は、この処理が正しく行われたことを確認する必要があります。
カスタム・ソケット・ファクトリを引数として取らないUnicastRemoteObject
上の古いコンストラクタまたはメソッドを使用してエクスポートされたリモート・オブジェクトでは、以前と同様に、UnicastRef
およびUnicastServerRef
型のRemoteRef
およびServerRef
が使用されます。このようなオブジェクトには、エンド・ポイントの古いワイヤー表現である、UTF形式のホスト文字列とそれに続くポート番号を指定する整数が使用されます。これは、新しい1.2の機能を使用しないRMIサーバーが、以前のバージョンのRMIクライアントとの相互運用を可能にするためです。
ソケット・ファクトリを指定せずにリモート・オブジェクトをエクスポートするか、RMIClientSocketFactory
およびRMIServerSocketFactory
型のパラメータを含まないバージョンのUnicastRemoteObject.exportObject
メソッドまたはUnicastRemoteObject
コンストラクタを使用してリモート・オブジェクトをエクスポートした場合、JavaランタイムはシステムのデフォルトのRMIソケット・ファクトリを使用します。このソケット・ファクトリは、すべてのインタフェースで受信待機するソケットをワイルドカード・アドレスで開きます。その結果、リモート・オブジェクトはすべてのローカル・アドレスにエクスポートされます。リモート・オブジェクトを特定のアドレスにエクスポートするには、次のいずれかを行います。
RMISocketFactory.setSocketFactory
メソッドを使用してソケット・ファクトリを指定します。RMIClientSocketFactory
およびRMIServerSocketFactory
インタフェースを実装し、UnicastRemoteObject.exportObject(Remote obj, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf)
メソッドを呼び出します。または、UnicastRemoteObject
クラスをサブクラス化し、UnicastRemoteObject(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf)
コンストラクタを呼び出します。この方法は、異なるインタフェースにバインドされた異なるオブジェクトをエクスポートできる点で、RMISocketFactory.setSocketFactory
メソッドを呼び出す方法よりも柔軟性があります。ただし、この方法はより複雑です。RMIClientSocketFactory
実装は、スタブに埋め込まれたインスタンスがクライアントに転送されるため、直列化可能である必要があります。RMIClientSocketFactory
実装クラスは、クライアントからアクセス可能にする必要があります。そのためには、通常、これらのクラスが利用可能な場所をポイントするようにクライアントのRMIコードベースを構成します。localhost
のみを含む)にアクセスを制限できる点で、柔軟性があります。この方法を使用すると、JavaランタイムはシステムのデフォルトのRMIソケット・ファクトリを使用します。このソケット・ファクトリは、すべてのインタフェースで受信待機するソケットを開きます。このソケットは、許可されないホスト、ドメイン、ネットワークからの接続も受け入れますが、RMI要求を処理せずにただちにそれらの接続を閉じます。RMISocketFactory
クラス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
インスタンスのためにこのメソッドを呼び出せるのは1回のみです。アプリケーションで定義する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を提供します。
createSocket
上で、ファクトリは直接ソケットによる接続ができないホストに自動的にHTTP接続を試みる。createServerSocket
上で、ファクトリはサーバー・ソケットを返し、新しく受け付けられた接続がHTTP POST要求かを自動検出する。そうであれば、トランスポートへの要求の本体だけを透過的に伝え、出力をHTTP応答として整形する。setFailureHandler
メソッドは、サーバー・ソケットの作成に失敗すると失敗用ハンドラをRMIランタイムにより呼び出されるように設定します。失敗用ハンドラはブール値を返して、リトライを行なってよいかどうかを示します。デフォルトの失敗用ハンドラはfalse
を返し、デフォルト条件ではランタイムはソケット作成のリトライを行わないことを示します。
getFailureHandler
メソッドは、ソケット作成失敗の現在のハンドラを返し、失敗用ハンドラが設定されていなければ、null
を返します。
RMIServerSocketFactory
インタフェースRMIServerSocketFactory
APIドキュメントを参照してください。
RMIClientSocketFactory
インタフェースRMIClientSocketFactory
APIドキュメントを参照してください。