| 目次|前|次 | 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ドキュメントを参照してください。