5 サーバー・インタフェース
RemoteObject
クラスRemoteServer
クラスUnicastRemoteObject
クラスUnreferenced
インタフェースRMISecurityManager
クラスRMIClassLoader
クラスLoaderHandler
インタフェース- RMIソケット・ファクトリ
RMIFailureHandler
インタフェースLogStream
クラス- スタブとスケルトン・コンパイラ
java.rmi.server
パッケージには、リモート・オブジェクトの実装に使われる典型的なインタフェースとクラスが含まれています。
5.1 RemoteObject
クラス
RemoteObject
APIドキュメントを参照してください。
5.2 RemoteServer
クラス
RemoteServer
APIドキュメントを参照してください。
5.3 UnicastRemoteObject
クラス
java.rmi.server.UnicastRemoteObject
クラスは、リモート・オブジェクトの作成とエクスポートをサポートします。 このクラスは、次の特性を持ったリモート・サーバー・オブジェクトを実装します。
- リモート・オブジェクトへの参照は、それを生成したプロセスの生存期間の間だけ有効である。
- リモート・オブジェクトとの通信ではTCPトランスポートを使用する。
- 呼び出し、パラメータ、および結果がクライアントとサーバー間通信のストリーム・プロトコルを使う。
package java.rmi.server;
public class UnicastRemoteObject extends RemoteServer {
protected UnicastRemoteObject()
throws java.rmi.RemoteException {...}
protected UnicastRemoteObject(int port)
throws java.rmi.RemoteException {...}
protected UnicastRemoteObject(int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws java.rmi.RemoteException {...}
public Object clone()
throws java.lang.CloneNotSupportedException {...}
public static RemoteStub exportObject(java.rmi.Remote obj)
throws java.rmi.RemoteException {...}
public static Remote exportObject(java.rmi.Remote obj, int port)
throws java.rmi.RemoteException {...}
public static Remote exportObject(Remote obj, int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws java.rmi.RemoteException {...}
public static boolean unexportObject(java.rmi.Remote obj,
boolean force)
throws java.rmi.NoSuchObjectException {...}
}
5.3.1新しいリモート・オブジェクトを作成する
1つ以上のリモート・インタフェースを実装するリモート・オブジェクト実装を作成し、エクスポートする必要があります。 リモート・オブジェクトをエクスポートすることにより、そのオブジェクトは、クライアントからの着信呼出しを受け入れることができるようになります。 UnicastRemoteObject
としてエクスポートされるリモート・オブジェクト実装の場合、エクスポートにはTCPポートでの待機が含まれます。ただし、同じポート上で複数のリモート・オブジェクトが着信呼出しを受け入れるので、必ずしも新しいポートで待機する必要はありません。 リモート・オブジェクト実装では、UnicastRemoteObject
クラスを拡張してオブジェクトをエクスポートするコンストラクタを利用するか、あるいは他のいくつかのクラスを拡張して(またはまったく拡張せずに) UnicastRemoteObject
のexportObject
メソッドを使用してオブジェクトをエクスポートできます。
引数を取らないコンストラクタは、リモート・オブジェクトを作成し、実行時に選択された匿名(または任意)のポートでエクスポートします。 2つ目の形式のコンストラクタは、portという引数を1つのみ取ります。この引数は、リモート・オブジェクトが着信呼出しを受け入れるポート番号を指定します。 3つ目のコンストラクタは、RMIServerSocketFactory
から作成されたServerSocket
を使用して、指定されたportの着信呼出しを受け入れるリモート・オブジェクトを作成してエクスポートします。クライアントは、RMIClientSocketFactory
から提供されたSocket
を使用してリモート・オブジェクトに接続します。
ソケット・ファクトリを指定せずにリモート・オブジェクトをエクスポートするか、RMIClientSocketFactory
およびRMIServerSocketFactory
型のパラメータを含まないバージョンのUnicastRemoteObject.exportObject
メソッドまたはUnicastRemoteObject
コンストラクタを使用してオブジェクトをエクスポートすると、リモート・オブジェクトはすべてのローカル・アドレスにエクスポートされます。 リモート・オブジェクトを特定のアドレスにエクスポートするには、"RMIソケット・ファクトリ"セクションを参照してください。
5.3.2 RemoteObject
からの拡張ではない実装のエクスポート
exportObject
メソッド(すべての形式)は、UnicastRemoteObject
クラスを拡張することでは実装されない単純なピアツーピア・リモート・オブジェクトをエクスポートするために使用します。 exportObject
メソッドの1つ目の形式は、objというパラメータを1つのみ取ります。これは、着信するRMI呼出しを受け入れるリモート・オブジェクトです。このexportObject
メソッドは、実行時に選択された匿名(または任意)のポートにオブジェクトをエクスポートします。 2つ目のexportObject
メソッドは、リモート・オブジェクトobj、およびリモート・オブジェクトが着信呼出しを受け入れるポート番号portの2つのパラメータを取ります。 3つ目のexportObject
メソッドは、指定されたRMIClientSocketFactory
、csf、RMIServerSocketFactory
ssfを使用して、指定されたportにオブジェクトobjをエクスポートします。
exportObject
メソッドは、リモート・オブジェクトobj
のスタブであり、リモート・オブジェクトの代わりにRMI呼出しで渡されたRemote
Stubを返します。
5.3.3 RMI呼出しでUnicastRemoteObject
を渡す
上述したように、RMI呼出しの中で、エクスポートされたUnicastRemoteObject
型のオブジェクトがパラメータまたは戻り値として渡されると、このオブジェクトは、リモート・オブジェクトのスタブに代わります。 エクスポートされたリモート・オブジェクトの実装は、それが作成された仮想マシン内にとどまり、仮想マシンから(値渡しによってさえ)移動しません。 すなわち、エクスポートされたオブジェクトはRMI呼出しでは参照渡しであり、エクスポートされたリモート・オブジェクトの実装は、値では渡すことができないということになります。
5.3.4 UnicastRemoteObject
を直列化する
UnicastRemoteObject
に含まれている情報は一時的であり、その型のオブジェクトがユーザー定義のObjectOutputStream
に書き込まれた場合には保存されません(たとえば、オブジェクトが直列化を使用してファイルに書き込まれる場合)。 ただし、UnicastRemoteObject
のユーザー定義サブクラスのインスタンスであるオブジェクトは、そのオブジェクトが直列化された場合でも保存可能な、非常駐データでないデータを持つことができます。
UnicastRemoteObject
が、UnicastRemoteObject
のreadObject
メソッドを使ってObjectInputStream
から読み込まれる場合、そのリモート・オブジェクトは、RMI呼出しを受け取れるようにRMIランタイムに自動的にエクスポートされます。 オブジェクトのエクスポートが何らかの原因で失敗した場合には、オブジェクトの直列化復元は、例外とともに途中で終了します。
5.3.5 UnicastRemoteObject
のアンエクスポート
unexportObject
メソッドを使うと、着呼がリモート・オブジェクトobjを利用できなくなります。 パラメータforceがtrueに設定されていると、リモート・オブジェクトへの保留状態の呼出しがある場合や、進行中の呼出しがある場合でも、オブジェクトは強制的にアンエクスポートされます。 forceパラメータがfalseの場合は、オブジェクトに対する保留中または進行中の呼出しがない場合だけ、オブジェクトがアンエクスポートされます。 オブジェクトが正常にアンエクスポートされた場合は、RMIのランタイムによってそのオブジェクトが内部テーブルから削除されます。 このような強制的な方法でオブジェクトをアンエクスポートすると、クライアントがリモート・オブジェクトへの無効なリモート参照を保持したままになることがあります。 オブジェクトが事前にRMIランタイムにエクスポートされなかった場合は、このメソッドはjava.rmi.NoSuchObjectException
をスローします。
5.3.6 clone
メソッド
オブジェクトの複製は、オブジェクトがjava.lang.Cloneable
インタフェースをサポートしている場合に、Java言語のデフォルトのメカニズムを使用することによってのみ可能になります。 java.rmi.server.UnicastRemoteObject
クラスは、このインタフェースを実装していませんが、サブクラスがCloneable
を実装する必要がある場合に、そのリモート・オブジェクトが正しく複製されるように、clone
メソッドを実装しています。 サブクラスは、clone
メソッドを使用して、始めの部分は同じ内容のリモート・オブジェクトの複製を作成できます。ただし、この複製は、エクスポートされてリモート呼出しを受け入れるため、元のオブジェクトとは別のオブジェクトです。
5.4 Unreferenced
インタフェース
package java.rmi.server;
public interface Unreferenced {
public void unreferenced();
}
java.rmi.server.Unreferenced
インタフェースを使うと、サーバー・オブジェクトが、自身に対するリモート参照を持っているクライアントがないという通知を受けることができます。 分散ガベージ・コレクション・メカニズムは、各リモート・オブジェクトについて、そのリモート・オブジェクトを参照しているクライアント仮想マシン群を保持しています。 あるクライアントがあるリモート・オブジェクトに対するリモート参照を持っている間は、RMIランタイムもそのリモート・オブジェクトへのローカル参照を保持し続けます。 リモート・オブジェクトの「参照」のセットが空になるたびに(つまり、そのオブジェクトを参照するクライアントの数が0になると)、リモート・オブジェクトがUnreferenced
インタフェースを実装していれば、Unreferenced.unreferenced
メソッドが呼び出されます。 リモート・オブジェクトがUnreferenced
インタフェースをサポートするのは必須ではありません。
リモート・オブジェクトに対するローカル参照が存在している間は、それをリモート呼出しで渡すこともできますし、クライアントへの戻り値にもなります。 参照を受け取ったプロセスは、そのリモート・オブジェクトに対するセットに追加されます。 参照セットが空になったとき、そのリモート・オブジェクトのunreferenced
メソッドが呼び出されます。 このため、unreferenced
メソッドは、参照セットがあらためて空になるたびに、何回も呼び出されます。 リモート・オブジェクトは、それに対する参照(ローカル参照またはクライアントが保持している参照)がなくなったときに回収されます。
5.5 RMISecurityManager
クラス
RMISecurityManager
APIドキュメントを参照してください。
5.6 RMIClassLoader
クラス
RMIClassLoader
APIドキュメントを参照してください。
5.7 LoaderHandler
インタフェース
LoaderHandler
APIドキュメントを参照してください。
5.8 RMIソケット・ファクトリ
RMIランタイム実装には、接続のために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を使用するアプリケーションがこれらの新しいソケット・ファクトリ・インタフェースを利用できるように、クライアントおよびサーバー・ソケット・ファクトリを追加パラメータとして取得するいくつかの新しいコンストラクタおよびexportObject
メソッドがUnicastRemoteObject
クラスに追加されました。
この新しいコンストラクタまたは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要求を処理せずにただちにそれらの接続を閉じます。
5.8.1 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
は、指定されたポート上にサーバー・ソケットを作成するものです。
setFailureHandler
メソッドは、サーバー・ソケットの作成に失敗すると失敗用ハンドラをRMIランタイムにより呼び出されるように設定します。 失敗用ハンドラはブール値を返して、リトライを行なってよいかどうかを示します。 デフォルトの失敗用ハンドラはfalse
を返し、デフォルト条件ではランタイムはソケット作成のリトライを行わないことを示します。
getFailureHandler
メソッドは、ソケット作成失敗の現在のハンドラを返し、失敗用ハンドラが設定されていなければ、null
を返します。
5.8.2 RMIServerSocketFactory
インタフェース
RMIServerSocketFactory
APIドキュメントを参照してください。
5.8.3 RMIClientSocketFactory
インタフェース
RMIClientSocketFactory
APIドキュメントを参照してください。
5.9 RMIFailureHandler
インタフェース
java.rmi.server.RMIFailureHandler
インタフェースは、サーバー・ソケットの作成に失敗した場合(オブジェクトのエクスポートの実行中を除く)に、RMIランタイムがどのように対応すればよいかを指定する手段を提供します。
package java.rmi.server;
public interface RMIFailureHandler {
public boolean failure(Exception ex);
}
failure
メソッドは、RMIランタイムがjava.net.ServerSocket
の作成に失敗した時の例外を引数として呼び出されます。 ランタイムがリトライするべき場合にメソッドはtrue
を返し、そうでない場合にはfalse
を返します。
このメソッドが呼び出される前に、失敗用ハンドラがRMISocketFactory.setFailureHandler
の呼出しによって登録されていなければなりません。 失敗用ハンドラが設定されていなければ、RMIランタイムはしばらく待ったあとに、ServerSocket
を再度作成しようとします。
オブジェクトの最初のエクスポート時にServerSocket
の作成に失敗した場合は、RMIFailureHandler
は呼び出されません。 作成の失敗がServerSocket
上で受け入れられたあとで、ServerSocket
を作成しようとすると、RMIFailureHandler
が呼び出されます。
5.10 LogStream
クラス
LogStream
APIドキュメントを参照してください。
5.11 スタブとスケルトン・コンパイラ
スタブおよびスケルトン・コンパイラrmic
は、特定のリモート・オブジェクト実装のためのスタブとスケルトンをコンパイルします。
rmic
の詳細については、次のURLを参照してください。
- LinuxおよびMacオペレーティング・システムの場合:
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/rmic.html
- Windowsプラットフォームの場合:
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/rmic.html