7 リモート・オブジェクト起動
7.1 概要
非推奨通知: RMIアクティブ化メカニズムは非推奨になり、将来のバージョンのプラットフォームから削除される可能性があります。 詳細は、JEP 385を参照してください。
分散オブジェクト・システムは、存続期間の長い永続オブジェクトをサポートするように設計されています。 たとえば、きわめて多数の永続オブジェクト(たとえば数百万個)で構成される分散オブジェクト・システムがあるとします。このシステムで、オブジェクトの実装が起動された後、ずっと起動された状態のままにするのは、貴重なシステム・リソースを無期限に占有し続けることになり、合理的ではありません。 また、一般に分散オブジェクトへの参照は、そのオブジェクトが起動されている間のみ有効であるため、システム・クラッシュ後にオブジェクト間の通信を確立しなおすことができるように、クライアント側ではオブジェクトへの永続性のある参照を保持しておく機能が必要になります。
オブジェクト起動は、オブジェクトへの永続性のある参照を提供するとともに、オブジェクトの実装の実行を管理するためのメカニズムです。 RMIでは、起動により必要に応じてオブジェクトの実行を開始できるようになっています。 メソッド呼出しにより、起動可能なリモート・オブジェクトへのアクセスがあったとき、そのリモート・オブジェクトが現在実行中でない場合は、適切なJVM内でそのオブジェクトの実行が開始されます。
7.1.1 用語
アクティブなオブジェクトとは、任意のシステム内の任意のJVM上でインスタンスが生成され、エクスポートされたリモート・オブジェクトを指します。 パッシブなオブジェクトとは、JVM上でまだインスタンスの生成(またはエクスポート)は行われていないが、アクティブな状態に移行可能なリモート・オブジェクトを指します。 パッシブなオブジェクトをアクティブなオブジェクトにすることを、起動といいます。 起動を行うためには、オブジェクトをJVMに関連付ける、つまり、そのオブジェクトのクラスをJVMにロードし、その永続状態を復元するオブジェクトを必要とします。
RMIシステムでは、遅延起動が使用されています。 遅延起動では、メソッドを呼び出すなど、クライアントがオブジェクトを最初に使用するまで、オブジェクトの起動が保留されます。
7.1.2遅延起動
リモート・オブジェクトの遅延起動は、フォルト・リモート参照 (フォルト・ブロックとも呼ばれる)により実現されています。 リモート・オブジェクトへのフォルト・リモート参照は、そのリモート・オブジェクトに対してメソッド呼出しが最初に行われたとき、アクティブなオブジェクトの参照で「障害を発生」させます。 それぞれのフォルト参照は、対象となるリモート・オブジェクトの永続ハンドル(起動識別子)と一時リモート参照の両方を保持しています。 リモート・オブジェクトの起動識別子には、該当するオブジェクトの起動時に第三者とやりとりするのに十分な情報が含まれています。 一時参照は、動作中のオブジェクトへのアクセスに使用できる、アクティブなリモート・オブジェクトへの実際の「ライブ」参照です。
フォルト参照では、リモート・オブジェクトへのライブ参照がnull
の場合、そのオブジェクトはアクティブではないものと見なされます。 メソッドの呼出しが発生すると、該当するオブジェクトのフォルト参照は、起動プロトコルを使用して、新たに起動されたオブジェクトのリモート参照(ユニキャスト・リモート参照など)である「ライブ」参照を取得します。 フォルト参照は、ライブ参照を取得すると、メソッド呼出しを背後のリモート参照に転送し、リモート参照は、今度はそれをリモート・オブジェクトに転送します。
より具体的に言えば、リモート・オブジェクトのスタブには、次の2つを含む「faulting」リモート参照型が含まれます。
リモート・オブジェクトの起動識別子
ユニキャストのセマンティックスを持つリモート参照型など、「アクティブ」なリモート参照型のリモート・オブジェクトが含まれる「ライブ」参照(
null
の場合もあり)。
ノート: RMIシステムは、リモート呼び出しのために"最大で1回"セマンティクスを保持します。 言い換えれば、起動可能またはユニキャストなリモート・オブジェクトの呼出しは、最大で1回までしか送られないということです。 したがって、リモート・オブジェクトの呼出しが失敗した場合(RemoteException
がスローされた場合)、クライアントは、そのリモート・メソッドが最大で1回しか実行されていない(通常は1回も実行されていない)ということを判断できます。
7.2 起動プロトコル
リモート・メソッドの呼出し時に、対象となるオブジェクトの「ライブ」参照がわからない場合、フォルト参照は起動プロトコルを利用します。 起動プロトコルは、いくつかのエンティティとかかわります。これらのエンティティは、フォルト参照、アクティベータ、起動グループおよび起動されているリモート・オブジェクトです。
アクティベータ(通常、ホストごとに1つ)は、起動を管理するエンティティで、次の2つの役割を持ちます。
起動識別子と、オブジェクトの起動に必要な情報(オブジェクトのクラス、オブジェクトのクラスのロード元を示すURL、オブジェクトがブートストラップのために必要とする特定のデータなど)とのマッピング情報のデータベースとしての役割
必要なときにJVMを起動するとともに、オブジェクトの起動要求をリモートJVM内の正しい起動グループに、必要な情報とともに転送するJava仮想マシンのマネージャとしての役割。
アクティベータは、現在の起動識別子とアクティブなオブジェクトとのマッピング情報をキャッシュとして保持しているので、起動要求のたびに起動グループに問い合わせをする必要はありません。
JVMごとに1つだけ存在する起動グループは、JVM内のオブジェクトの起動要求を受け取り、起動されたオブジェクトをアクティベータに返すエンティティです。
起動プロトコルは、次のような働きをします。 まず、フォルト参照は起動識別子を使用してアクティベータ(内部RMIインタフェース)を呼び出し、起動識別子に関連付けられたオブジェクトを起動します。 次に、アクティベータはオブジェクトの起動記述子 (前に登録したもの)を参照します。 オブジェクトの記述子には、次の情報が含まれます。
- オブジェクトのグループ識別子(オブジェクトが起動されるJVMを示す)
- オブジェクトのクラス名
- オブジェクトのクラス・コードのロード元を示すURLパス、および
- オブジェクト固有の整列化された形式の初期化データ(たとえば、オブジェクトの永続状態が含まれたファイルの名前など)。
該当するオブジェクトが属すべき起動グループが存在する場合は、アクティベータは起動要求をそのグループに転送します。 そのような起動グループが存在しない場合は、JVMに起動グループを起動させ、その起動グループに起動要求を転送します。
起動グループは、該当するオブジェクトのクラスをロードし、いくつかの引数(前に登録した起動記述子など)をとる特別なコンストラクタを使ってオブジェクトのインスタンスを生成します。
オブジェクトの起動が完了すると、起動グループは整列化されたオブジェクトの参照をアクティベータに返し、それを受け取ったアクティベータは、起動識別子とアクティブな参照のペアを記録して、アクティブな(ライブ)参照をフォルト参照に返します。 次に、フォルト参照(スタブ内)は、リモート・オブジェクトへの直接のライブ参照を介してメソッド呼出しを転送します。
ノート: Java 2 SDK、Standard Edition、v 1.2では、RMIはシステム・インタフェースの実装を提供します。 起動を使用するには、事前に起動システム・デーモンrmid
を動作させておく必要があります。
7.3 「起動可能」リモート・オブジェクトの実装モデル
起動識別子を介してアクセスできるリモート・オブジェクトを作成するには、次のような準備が必要です。
- リモート・オブジェクトの起動記述子を登録する
- 起動可能オブジェクトを起動するときにRMIシステムが呼び出す特別なコンストラクタを、オブジェクトのクラスに含める。
起動記述子(ActivationDesc
)は、次のどれかの方法で登録できます。
Activatable
クラスのstaticメソッドregister
を呼び出すActivatable
クラスの1つ目または2つ目のコンストラクタを使用して「起動可能」オブジェクトを作成するActivatable
の1つ目または2つ目のexportObject
メソッドを使用して「起動可能」オブジェクトを明示的にエクスポートする。
起動用にオブジェクトを登録するときは、前述のどれか1つの方法のみを使用してください。複数の方法を使用しないでください。 起動可能オブジェクトの実装方法の例については、後述する「起動可能リモート・オブジェクトの構築」のセクションを参照してください。
7.3.1 ActivationDesc
クラス
ActivationDesc
には、オブジェクトの起動に必要な情報が含まれます。 具体的には、オブジェクトの起動グループ識別子、オブジェクトのクラス名、オブジェクトのコードのロード元のコードベース・パス(URL)、および、起動のたびに使用されるオブジェクト固有の初期化データが含まれるMarshalledObject
が含まれます。
起動システムに登録された記述子は、オブジェクトの再作成または起動に必要な情報を取得するため、起動プロセス中に参照されます。 オブジェクトの記述子に含まれるMarshalledObject
は、オブジェクトのリモート・オブジェクトのコンストラクタに2番目の引数として、起動時に使用するために渡されます。
package java.rmi.activation;
public final class ActivationDesc implements java.io.Serializable
{
public ActivationDesc(String className,
String codebase,
java.rmi.MarshalledObject data)
throws ActivationException;
public ActivationDesc(String className,
String codebase,
java.rmi.MarshalledObject data,
boolean restart)
throws ActivationException;
public ActivationDesc(ActivationGroupID groupID,
String className,
String codebase,
java.rmi.MarshalledObject data,
boolean restart);
public ActivationDesc(ActivationGroupID groupID,
String className,
String codebase,
java.rmi.MarshalledObject data);
public ActivationGroupID getGroupID();
public String getClassName();
public String getLocation();
public java.rmi.MarshalledObject getData()
public boolean getRestartMode();
}
ActivationDesc
の1つ目のコンストラクタは、オブジェクト記述子を構築します。対象となるオブジェクトは、クラスがcodebaseで指定されたコードベース・パスからロードできるclassNameであり、整列化された形式の初期化情報がdataであるオブジェクトです。 この形式のコンストラクタが使用される場合、オブジェクトのグループ識別子は、デフォルトでそのJVMのActivationGroup
の現在の識別子になります。 同じActivationGroupID
を持つオブジェクトは、すべて同じJVM内で起動されます。 現在のグループがアクティブでない場合は、ActivationException
をスローします。 groupIDがnull
の場合は、IllegalArgumentException
がスローされます。
ActivationDesc
の2つ目のコンストラクタは、1つ目のコンストラクタと同じようにしてオブジェクト記述子を構築しますが、パラメータrestartも指定する必要があります。 オブジェクトの再起動サービスを必要とする場合、つまり、アクティベータの再起動時にオブジェクトが自動的に再起動されるようにするには(必要なときに遅延起動するのとは反対)、restartにtrue
を指定します。 restartにfalse
を指定すると、オブジェクトは必要なときにのみリモート・メソッド呼出しにより起動されます。
ActivationDesc
の3つ目のコンストラクタは、グループ識別子がgroupIDで、クラス名が、codebaseで指定されたコードベース・パスからロードできるclassName、および初期化情報がdataであるオブジェクトのオブジェクト記述子を構築します。 同じgroupIDを持つオブジェクトは、すべて同じJVM内で起動されます。
ActivationDesc
の4つ目のコンストラクタは、3つ目のコンストラクタと同じようにしてオブジェクト記述子を構築しますが、再起動モードを指定できるようになっています。 前述したオブジェクトの再起動サービスが必要な場合は、restartにtrue
を指定します。
getGroupID
メソッドは、記述子で指定されたオブジェクトのグループ識別子を返します。 グループは、複数のオブジェクトを1つのJava仮想マシンにまとめる役割を果たします。
getClassName
メソッドは、起動記述子で指定されたオブジェクトのクラス名を返します。
getLocation
メソッドは、オブジェクトのクラスのダウンロード元となるコードベース・パスを返します。
getData
メソッドは、記述子で指定されたオブジェクトの初期化または起動データが含まれる「整列化されたオブジェクト」を返します。
getRestartMode
メソッドは、このオブジェクトの再起動モードが有効になっている場合はtrue
を返し、無効になっている場合はfalseを返します。
7.3.2 ActivationID
クラス
起動プロトコルでは、起動識別子を使用して、しばらく起動可能なリモート・オブジェクトを表します。 起動識別子(ActivationID
クラスのインスタンス)には、オブジェクトを起動するために必要な次のような情報が含まれています。
- オブジェクトのアクティベータへのリモート参照
- オブジェクトの一意の識別子。
オブジェクトの起動識別子は、オブジェクトを起動システムに登録することで取得できます。 登録は次のような方法で行えます(前述の内容にも留意のこと)。
Activatable.register
メソッドを使用するActivatable
の1つ目または2つ目のコンストラクタ(オブジェクトの登録とエクスポートの両方を行う)を使用する- 1つ目または2つ目の
Activatable.exportObject
メソッド(オブジェクトの登録とエクスポートの両方を行う)を使用する。
package java.rmi.activation;
public class ActivationID implements java.io.Serializable
{
public ActivationID(Activator activator);
public Remote activate(boolean force)
throws ActivationException, UnknownObjectException,
java.rmi.RemoteException;
public boolean equals(Object obj);
public int hashCode();
}
ActivationID
のコンストラクタは、activatorという引数のみを取ります。この引数には、この起動識別子に関連付けられたオブジェクトを起動するアクティベータへのリモート参照を指定します。 ActivationID
のインスタンスは、大域的に一意です。
activate
メソッドは、起動識別子に関連付けられたオブジェクトを起動します。 forceパラメータにtrueを指定すると、キャッシュされているリモート・オブジェクトの参照は古い参照であると見なされ、オブジェクトの起動時にはグループへの問い合わせが強制的に行われます。 forceにfalseを指定すると、キャッシュされた値が使用されます。 起動に失敗した場合は、ActivationException
がスローされます。 オブジェクト識別子がアクティベータに認識されない識別子である場合、メソッドはUnknownObjectException
をスローします。 アクティベータへのリモート呼出しが失敗した場合は、RemoteException
がスローされます。
equals
メソッドは、内容が等しいかどうかをチェックするメソッドです。 このメソッドは、すべてのフィールドが等価(各フィールドのObject.equals
のセマンティックスに照らし合わせて同一または等価)である場合はtrue
を返します。 p1とp2がActivationID
クラスのインスタンスであるとすると、p1.equals(p2)
がtrue
を返す場合は、hashCode
メソッドは同じ値を返します。
7.3.3 Activatable
クラス
Activatable
クラスは、永続的なアクセスを必要とし、システムから起動できるリモート・オブジェクトをサポートします。 Activatable
クラスは、起動可能オブジェクトの実装および管理に使用する必要のある中心的なAPIです。 なお、オブジェクトの登録や起動を行うためには、事前に起動システム・デーモンrmid
を動作させておく必要があります。
package java.rmi.activation;
public abstract class Activatable
extends java.rmi.server.RemoteServer
{
protected Activatable(String codebase,
java.rmi.MarshalledObject data,
boolean restart,
int port)
throws ActivationException, java.rmi.RemoteException;
protected Activatable(String codebase,
java.rmi.MarshalledObject data,
boolean restart, int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws ActivationException, java.rmi.RemoteException;
protected Activatable(ActivationID id, int port)
throws java.rmi.RemoteException;
protected Activatable(ActivationID id, int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws java.rmi.RemoteException;
protected ActivationID getID();
public static Remote register(ActivationDesc desc)
throws UnknownGroupException, ActivationException,
java.rmi.RemoteException;
public static boolean inactive(ActivationID id)
throws UnknownObjectException, ActivationException,
java.rmi.RemoteException;
public static void unregister(ActivationID id)
throws UnknownObjectException, ActivationException,
java.rmi.RemoteException;
public static ActivationID exportObject(Remote obj,
String codebase,
MarshalledObject data,
boolean restart,
int port)
throws ActivationException, java.rmi.RemoteException;
public static ActivationID exportObject(Remote obj,
String codebase,
MarshalledObject data,
boolean restart,
int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws ActivationException, java.rmi.RemoteException;
public static Remote exportObject(Remote obj,
ActivationID id,
int port)
throws java.rmi.RemoteException;
public static Remote exportObject(Remote obj,
ActivationID id,
int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws java.rmi.RemoteException;
public static boolean unexportObject(Remote obj, boolean force)
throws java.rmi.NoSuchObjectException;
}
起動可能リモート・オブジェクトの実装は、Activatable
クラスを拡張しているかどうかに依存しません。 Activatable
クラスを拡張するリモート・オブジェクトの実装では、スーパー・クラスjava.rmi.server.RemoteObject
から適切なhashCode
メソッドとequals
メソッドの定義が継承されます。 したがって、同一のActivatable
リモート・オブジェクトを参照する2つのリモート・オブジェクト参照は等価になります(equals
メソッドがtrueを返す)。 また、Activatable
クラスのインスタンスは、その適切なスタブ・オブジェクトと等しくなります。たとえば、Object.equals
メソッドを、その引数にオブジェクトの実装に対応するスタブ・オブジェクトを指定して呼び出すと、trueが返されます(逆の場合も同様)。
Activatable
クラス・メソッド
Activatable
クラスの1つ目のコンストラクタは、オブジェクトの登録と指定されたポート(port)でのオブジェクトのエクスポートに使用します。portにゼロを指定した場合は匿名ポートが選ばれます。 codebaseには、オブジェクトのクラス・コードのダウンロード元となるURLパスを指定し、dataにはその初期化データを指定します。 restartにtrue
を指定すると、アクティベータが再起動し、かつグループがクラッシュした場合に、オブジェクトが自動的に再起動されるようになります。 restartにfalse
を指定すると、オブジェクトは必要なときにのみリモート・メソッド呼出しによって起動されるようになります。
このコンストラクタは、オブジェクトを最初の構築時に登録およびエクスポートするため、Activatable
クラスの具象サブクラスから呼び出さなければなりません。 起動可能オブジェクト構築の副作用として、クライアントからの呼出しに応じられるように、リモート・オブジェクトが起動システムに「登録」されると同時にRMIランタイムに「エクスポート」されます(portにゼロを指定した場合は匿名ポートで)。
このコンストラクタは、起動システムへのオブジェクトの登録が失敗した場合はActivationException
をスローします。 RMIランタイムへのオブジェクトのエクスポートが失敗した場合はRemoteException
をスローします。
2つ目のコンストラクタは、Activatable
の最初のコンストラクタと同じですが、この起動可能オブジェクトとのやりとりに使用するクライアント・ソケット・ファクトリとサーバー・ソケット・ファクトリを指定できるようになっています。 詳細については、"RMIソケット・ファクトリ"のセクションを参照してください。
3つ目のコンストラクタは、オブジェクトの起動と指定されたポートportでのオブジェクトのエクスポート(ActivationID
idを使用)に使用します。 このコンストラクタは、オブジェクト自身が、次のパラメータをとる特別な「起動」コンストラクタにより起動されるときにActivatable
クラスの具象サブクラスから呼び出さなければなりません。
- オブジェクトの起動識別子(
ActivationID
) - オブジェクトの初期化データやブートストラップ・データ(
MarshalledObject
)。
起動可能なオブジェクトを構築すると、指定されたport上のRMIランタイムにリモート・オブジェクトが「エクスポート」され、クライアントからの着信呼出しの受け付けに使用できるようになります。 このコンストラクタは、RMIランタイムへのオブジェクトのエクスポートが失敗した場合はRemoteException
をスローします。
4つ目のコンストラクタは3つ目のコンストラクタと同じですが、この起動可能オブジェクトとのやりとりに使用するクライアント・ソケット・ファクトリとサーバー・ソケット・ファクトリを指定できるようになっています。
getID
メソッドは、オブジェクトの起動識別子を返します。 このメソッドは、サブクラスだけがオブジェクトの識別子を取得できるように保護されています。 オブジェクトの識別子は、オブジェクトがアクティブでないことを報告する場合、またはオブジェクトの起動記述子の登録を解除する場合に使用します。
register
メソッドは、起動可能リモート・オブジェクトを必要なときに起動できるように、そのオブジェクト記述子descを起動システムに登録します。 このメソッドを使用するのは、起動可能オブジェクトを事前に作成しないで登録するときです。 このメソッドは、起動可能オブジェクトのRemote
スタブを返します。これを保存し、後で呼び出すことにより、起動可能オブジェクトが初めて作成および起動されます。 descのグループ識別子が起動システムに登録されていない場合、このメソッドはUnknownGroupException
をスローします。 起動システムが動作していない場合は、ActivationException
がスローされます。 また、起動システムのリモート呼出しが失敗した場合はRemoteException
をスローします。
inactive
メソッドは、指定した起動idを持つオブジェクトが現在アクティブでないことをシステムに知らせるために使用します。 現時点でアクティブとされているオブジェクトは、クライアントからの呼出しを受けないようにRMIランタイムからアンエクスポートされます(保留状態の呼出しや実行中の呼出しがない場合のみ)。 また、このメソッドを呼び出すと、このJVMのActivationGroup
にもオブジェクトがアクティブでないことが知らされ、これを受けて、ActivationGroupは、そのActivationMonitor
にオブジェクトがアクティブでないことを知らせます。 このメソッドの呼出しが成功した場合、それ以降、アクティベータに対して起動要求があると、オブジェクトは再度起動されます。 inactive
メソッドは、オブジェクトのアンエクスポートに成功した場合、つまり、保留状態の呼出しや実行中の呼出しがない場合はtrue
を返し、保留状態の呼出しや実行中の呼出しが存在するためにオブジェクトをアンエクスポートできなかった場合はfalse
を返します。 指定したオブジェクトがアクティベータに認識されないオブジェクトである場合(すでにアクティブでなくなっている可能性がある)、このメソッドはUnknownObjectException
をスローします。グループがアクティブでない場合はActivationException
をスローします。モニターにオブジェクトがアクティブでないことを知らせるのに失敗した場合はRemoteException
をスローします。 オブジェクトがアクティブであると見られる場合であっても、すでにアンエクスポートされている場合は、このメソッドの呼出しは成功することがあります。
unregister
メソッドは、idに関連付けられた起動記述子の登録を解除します。 オブジェクトはそのidで起動できなくなります。 オブジェクトidが起動システムの知らない識別子である場合は、UnknownObjectException
がスローされます。 起動システムが動作していない場合は、ActivationException
がスローされます。 起動システムのリモート呼出しが失敗した場合は、RemoteException
がスローされます。
1つ目のexportObject
メソッドは、Activatable
クラスを拡張していない「起動可能」オブジェクトから明示的に呼び出すことができます。このメソッドは、次の2つの目的に使用します。
オブジェクトを起動できるように、指定されたcodebaseとdataから構築されたオブジェクトの起動記述子descを起動システムに登録する
リモート・オブジェクトobjを特定のポートportでエクスポートする。 portにゼロを指定した場合は匿名ポートが選ばれる。
エクスポートされたオブジェクトは、RMI呼出しを受け取ることができるようになります。
このexportObject
メソッドは、起動記述子descを起動システムに登録して取得した起動識別子を返します。 起動グループがJVMでアクティブになっていない場合は、ActivationException
がスローされます。 オブジェクトの登録またはエクスポートが失敗した場合は、RemoteException
がスローされます。
objがextends節でActivatable
を拡張している場合は、Activatable
の1つ目のコンストラクタがこのメソッドを呼び出すため、このメソッドを呼び出す必要はありません。
2つ目のexportObject
メソッドは、1つ目のexportObjectメソッドと同じですが、起動可能オブジェクトとのやりとりに使用するクライアント・ソケット・ファクトリとサーバー・ソケット・ファクトリを指定できるようになっています。
3つ目のexportObject
メソッドは、識別子idを持つ「起動可能」リモート・オブジェクト(必ずしもActivatable
型である必要はない)をRMIランタイムにエクスポートし、オブジェクトobjがクライアントからの呼出しに応じられるようにします。 portにゼロを指定した場合は、オブジェクトは匿名ポートでエクスポートされます。
起動時に、exportObject
メソッドは、Activatable
クラスを拡張しない「起動可能な」オブジェクトから明示的に呼び出される必要があります。 Activatable
クラスを拡張しているオブジェクトの場合は、このメソッドを直接呼び出す必要はありません。この場合、このメソッドは前述の3つ目のコンストラクタ(サブクラスがその特別な起動コンストラクタから呼び出すコンストラクタ)により呼び出されます。
このexportObject
メソッドは、起動可能オブジェクトのRemote
スタブを返します。 オブジェクトのエクスポートに失敗した場合は、このメソッドはRemoteException
をスローします。
4つ目のexportObject
メソッドは3つ目のexportObjectメソッドと同じですが、この起動可能オブジェクトとのやりとりに使用するクライアント・ソケット・ファクトリとサーバー・ソケット・ファクトリを指定できるようになっています。
unexportObject
メソッドを使うと、着呼がリモート・オブジェクトobjを利用できなくなります。 パラメータforceがtrue
に設定されていると、リモート・オブジェクトへの保留状態の呼出しがある場合や、進行中の呼出しがある場合でも、オブジェクトは強制的にアンエクスポートされます。 forceパラメータがfalse
の場合は、オブジェクトに対する保留中または進行中の呼出しがない場合だけ、オブジェクトがアンエクスポートされます。 オブジェクトが正常にアンエクスポートされた場合は、RMIのランタイムによってそのオブジェクトが内部テーブルから削除されます。 RMIから強制的にオブジェクトを削除すると、クライアントはそのリモート・オブジェクトへの古い参照を保持したままになってしまう可能性があります。 オブジェクトが事前にRMIランタイムにエクスポートされなかった場合は、このメソッドはjava.rmi.NoSuchObjectException
をスローします。
Activatable
リモート・オブジェクトの作成
オブジェクトを起動できるようにするには、「起動可能」オブジェクトの実装クラス(Activatable
クラスを拡張しているかどうかにかかわらず)で、その起動識別子(ActivationID
型のもの)と、その起動データjava.rmi.MarshalledObject
(登録時に使用した起動識別子で提供したもの)の2つの引数をとる特別なpublicコンストラクタを定義する必要があります。 起動グループは、そのJVM内でリモート・オブジェクトを起動するときに、この特別なコンストラクタを使用してリモート・オブジェクトを構築します(詳細は後述)。 リモート・オブジェクトの実装では、適切な方法により自分自身を初期化するために、起動データが使用される可能性があります。 リモート・オブジェクトは、起動識別子を保持して、起動グループが非アクティブ(Activatable.inactive
メソッドの呼び出しを介して)になったことを通知できるようにすることもできます。
Activatable
の1つ目と2つ目のコンストラクタは、起動可能オブジェクトの登録と、指定されたポート(port)でのオブジェクトのエクスポートの両方に使用されます。 このコンストラクタは、オブジェクトを最初に構築するときに使用してください。3つ目のコンストラクタは、オブジェクトを再度起動するときに使用します。
Activatable
の具象サブクラスでは、最初の構築時には1つ目または2つ目のコンストラクタ形式を呼び出して、オブジェクトの登録とエクスポートを行う必要があります。 このコンストラクタは、まず、オブジェクトのクラス名とオブジェクト用に提供されたcodebaseおよびdataにより起動記述子(ActivationDesc
)を作成します。また、その起動グループはJVMのデフォルトのグループになります。 次に、コンストラクタはこの記述子をデフォルトのActivationSystem
に登録します。 最後に、起動可能オブジェクトを特定のポート(port)でRMIランタイムにエクスポートし(portにゼロを指定した場合は匿名ポートが選ばれる)、オブジェクトをactiveObject
としてローカルなActivationGroup
に報告します。 登録中かエクスポート中にエラーが発生した場合は、このコンストラクタはRemoteException
をスローします。 なお、それ以降のprotectedメソッドgetID
の呼出しでオブジェクトの起動識別子が返されるように、このコンストラクタはオブジェクトのActivationID
(登録により取得したもの)の初期化も行います。
Activatable
の3つ目のコンストラクタ形式は、指定されたポートでのオブジェクトのエクスポートに使用されます。 この3つ目のコンストラクタ形式は、オブジェクト自身が次の2つの引数をとるオブジェクト自身の「起動」コンストラクタにより起動されるときにActivatable
クラスの具象サブクラスから呼び出さなければなりません。
- オブジェクト
ActivationID
- オブジェクトの初期化データ
MarshalledObject
このコンストラクタは、指定したポート (portにゼロを指定した場合は匿名ポートが選ばれる)で起動可能オブジェクトをRMIランタイムにエクスポートするだけです。 オブジェクトはActivationGroup
によって起動されており、オブジェクトがアクティブになっていることはすでに知られているため、オブジェクトがアクティブであることをActivationGroup
に知らせることはしません。
次のコードは、リモート・オブジェクト・インタフェースServer
と、extends節でActivatable
を拡張したServerImpl
の実装例です。
package examples;
public interface Server extends java.rmi.Remote {
public void doImportantStuff()
throws java.rmi.RemoteException;
}
public class ServerImpl extends Activatable implements Server
{
// Constructor for initial construction, registration and export
public ServerImpl(String codebase, MarshalledObject data)
throws ActivationException, java.rmi.RemoteException
{
// register object with activation system, then
// export on anonymous port
super(codebase, data, false, 0);
}
// Constructor for activation and export; this constructor
// is called by the ActivationInstantiator.newInstance
// method during activation in order to construct the object.
public ServerImpl(ActivationID id, MarshalledObject data)
throws java.rmi.RemoteException
{
// call the superclass's constructor in order to
// export the object to the RMI runtime.
super(id, 0);
// initialize object (using data, for example)
}
public void doImportantStuff() { ... }
}
オブジェクトのエクスポートは、オブジェクトそのものが担当します。 Activatable
のコンストラクタは、UnicastRemoteObject
型のライブ参照によりオブジェクトをRMIランタイムにエクスポート処理します。したがって、Activatable
クラスを拡張しているオブジェクトの実装では、適切なスーパー・クラスのコンストラクタを呼び出す場合を除いて、オブジェクトを明示的にエクスポートする必要はありません。 Activatable
クラスを拡張していないオブジェクトの実装では、staticメソッドActivatable.exportObject
のいずれかを呼び出してオブジェクトを明示的にエクスポートする必要があります。
次の例では、ServerImpl
はActivatable
ではなく別のクラスを拡張しています。したがって、ServerImpl
は、最初の構築時と起動時に自分自身のエクスポートを担当します。 このクラス定義には、ServerImpl
の初期化コンストラクタと特別な「起動」コンストラクタがあります。それぞれのコンストラクタの中では、オブジェクトをエクスポートするため、所定の呼出しを行っています。
package examples;
public class ServerImpl extends SomeClass implements Server
{
// constructor for initial creation
public ServerImpl(String codebase, MarshalledObject data)
throws ActivationException, java.rmi.RemoteException
{
// register and export the object
Activatable.exportObject(this, codebase, data, false, 0);
}
// constructor for activation
public ServerImpl(ActivationID id, MarshalledObject data)
throws java.rmi.RemoteException
{
// export the object
Activatable.exportObject(this, id, 0);
}
public void doImportantStuff() { ... }
}
オブジェクトを作成しないで起動記述子を登録する
起動可能リモート・オブジェクトを、先に作成しないで起動システムに登録するには、その起動記述子(ActivationDesc
クラスのインスタンス)を登録するのみでかまいません。 起動記述子には、必要時に起動システムがオブジェクトを起動するのに必要なすべての情報が含まれています。 examples.ServerImpl
クラスのインスタンスの起動記述子は、次のようにして登録できます。なお、例外処理は省略しています。
Server server;
ActivationDesc desc;
String codebase = "http://zaphod/codebase/";
MarshalledObject data = new MarshalledObject("some data");
desc = new ActivationDesc( "examples.ServerImpl", codebase, data);
server = (Server)Activatable.register(desc);
register
の呼出し行では、examples.ServerImpl
オブジェクトのスタブであり、examples.ServerImpl
で実装されているのと同じリモート・インタフェースを実装したRemote
スタブが返されます。たとえば、このRemoteスタブではリモート・インタフェースServer
が実装されています。 キャストされてserverに代入されている、このスタブ・オブジェクトは、リモート・インタフェースexamples.Server
を実装したオブジェクトを取るメソッドにパラメータとして渡すことができます。
7.4 起動インタフェース
RMI起動プロトコルでは、システムの正常な動作のため、アクティベータに関して守るべき次の2つの約束事があります。
- すべてのシステム・デーモン同様、アクティベータはマシンが動作している間、常に動作させておくこと
- アクティベータは、すでにアクティブな状態のリモート・オブジェクトを起動しないこと。
アクティベータは、起動処理に関与するグループとオブジェクトに対する適切な情報のデータベースを保持します。
7.4.1 Activator
インタフェース
アクティベータは、起動プロセス中に関与するエンティティの1つです。 前述したように、フォルト参照(スタブ内)は、起動可能リモート・オブジェクトへの「ライブ」参照を取得するため、アクティベータのactivate
メソッドを呼び出します。 アクティベータは、起動要求を受け取ると、指定された起動識別子idに対応する起動記述子を探し、そのオブジェクトを起動すべきグループを特定して、その起動グループのインスタンシエータのnewInstance
メソッドを呼び出します(リモート・インタフェースActivationGroup
については後述)。 必要であれば、アクティベータは起動グループの実行を開始します。 たとえば、特定のグループ記述子に対応する起動グループがまだ実行されていない場合、アクティベータはその起動グループの子JVMを生成し、生成したJVM内で起動グループを立ち上げます。
アクティベータは、起動グループのエラーを監視、検出し、エラーの際は、その内部テーブルから古いリモート参照を削除します。
package java.rmi.activation;
public interface Activator extends java.rmi.Remote
{
java.rmi.MarshalledObject activate(ActivationID id,
boolean force)
throws UnknownObjectException, ActivationException,
java.rmi.RemoteException;
}
activate
メソッドは、起動識別子idに関連付けられたオブジェクトを起動します。 そのオブジェクトがすでにアクティブな状態にあることをアクティベータが知っており、なおかつforceパラメータがfalseの場合は、スタブが「ライブ」参照とともにただちに呼出し側に返されます。一方、対応するリモート・オブジェクトがアクティブな状態にあることをアクティベータが知らないか、forceパラメータがtrue
の場合は、アクティベータは起動記述子情報(前にidを取得するため登録したもの)を使用して、オブジェクトを起動する必要があるグループ(JVM)を特定します。 特定したオブジェクトのグループに対応するActivationInstantiator
がすでに存在する場合、アクティベータは起動インスタンシエータのnewInstance
メソッドを呼び出し、オブジェクトのidと起動記述子を引数として渡します。
特定したオブジェクトのグループ記述子に対応する起動インスタンシエータまたはグループがまだ存在しない場合は、アクティベータは、子プロセスを生成するなどの方法によりActivationInstantiator
の実行の新規生成を開始させます。 アクティベータは、特定のグループのActivationInstantiator
を再作成するときは、そのグループの生成番号をインクリメントしなければなりません。 生成番号はゼロから始まります。 起動システムは、生成番号により、新しいActivationSystem.activeGroup
およびActivationMonitor.inactiveGroup
の呼出しを検出します。 同じグループで、現在の生成番号よりも若い生成番号を持つ呼出しは破棄されます。
ノート: ベータは、新しいグループを起動するときに、グループ識別子、記述子、およびインカネーション番号の両方を通知する必要があります。 アクティベータは、独立したJVM内で(たとえば、別のプロセスや子プロセスとして)起動グループを生成します。したがって、アクティベータは、ActivationGroup.createGroup
メソッドで起動グループを作成するのに必要な情報を引き渡す必要があります。 この情報を生成されたプロセスにどのように引き渡すかについては規定されていませんが、整列化されたオブジェクトの形式で子プロセスの標準入力に送ることが可能です。
アクティベータは、ActivationSystem.activeGroup
メソッドにより起動グループの参照と生成番号が含まれる起動グループのコールバックを受け取ると、その起動インスタンシエータのnewInstance
メソッドを呼び出して、保留状態になっている起動要求を起動インスタンシエータに転送し、結果(整列化されたリモート・オブジェクトの参照、つまりスタブ)をそれぞれの呼出し側に返すことができます。
アクティベータは、Remote
オブジェクトではなくMarshalledObject
を受け取ることによって、オブジェクトのコードのロードやオブジェクトの分散ガベージ・コレクションへの関与の必要性をなくしています。 リモート・オブジェクトへの強い参照を保持していれば、通常の分散ガベージ・コレクション・メカニズムの下では、アクティベータはリモート・オブジェクトがガベージ・コレクトされるのを防ぐことができます。
起動が失敗した場合、activate
メソッドはActivationException
をスローします。 起動が失敗する原因としては、クラスが見つからない、起動グループにアクセスできないなど、様々な要因があります。指定された起動識別子idに対応する起動記述子がこのアクティベータに登録されていない場合、activate
はUnknownObjectException
をスローします。 アクティベータへのリモート呼出しが失敗した場合は、RemoteException
がスローされます。
7.4.2 ActivationSystem
インタフェース
ActivationSystem
は、グループ、およびその中にある起動可能なオブジェクトのうちで起動しておくものを登録する方法を提供します。 ActivationSystem
は、ActivationSystem
で登録されたオブジェクトを起動するActivator
と、アクティブなオブジェクトや、アクティブでないオブジェクト、またはアクティブでないグループに関する情報を取得するActivationMonitor
の双方と密接に関連しながら動作します。
package java.rmi.activation;
public interface ActivationSystem extends java.rmi.Remote
{
public static final int SYSTEM_PORT = 1098;
ActivationGroupID registerGroup(ActivationGroupDesc desc)
throws ActivationException, java.rmi.RemoteException;
ActivationMonitor activeGroup(ActivationGroupID id,
ActivationInstantiator group,
long incarnation)
throws UnknownGroupException, ActivationException,
java.rmi.RemoteException;
void unregisterGroup(ActivationGroupID id)
throws ActivationException, UnknownGroupException,
java.rmi.RemoteException;
ActivationID registerObject(ActivationDesc desc)
throws ActivationException, UnknownGroupException,
java.rmi.RemoteException;
void unregisterObject(ActivationID id)
throws ActivationException, UnknownObjectException,
java.rmi.RemoteException;
void shutdown() throws java.rmi.RemoteException;
}
ノート: セキュリティ対策として、上記のすべてのメソッド(registerGroup
、activeGroup
、unregisterGroup
、registerObject
、unregisterObject
、およびshutdown
)は、起動システムと同じホストに存在しないクライアントから呼び出された場合、java.rmi.RemoteException,
のサブクラスjava.rmi.AccessException
をスローします。
registerObject
メソッドは、起動記述子descの登録と、起動可能リモート・オブジェクトの起動識別子の取得に使用します。 ActivationSystem
は、起動記述子descで指定されたオブジェクトのActivationID
(起動識別子)を作成し、後の使用に備えて起動記述子と、それに関連付けられた識別子を安定ストレージに記録します。 Activator
は、特定の識別子を対象としたactivate
要求を受け取ると、指定された識別子に対応する起動記述子(前に登録したもの)を探し、その情報を使用してオブジェクトを起動します。 descで参照されているグループがこのシステムに登録されていない場合は、メソッドはUnknownGroupException
をスローします。 データベースの更新の失敗などが原因で登録が失敗した場合は、ActivationException
をスローします。 リモート呼出しが失敗した場合は、RemoteException
をスローします。
unregisterObject
は、起動識別子idと、それに関連付けられ、ActivationSystem
に登録されている記述子を削除します。 呼出し完了後は、オブジェクトはその起動idでは起動できなくなります。 指定されたオブジェクトidが起動システムに認識されない(登録されていない)識別子である場合は、メソッドはUnknownObjectException
をスローします。 データベース更新の失敗などが原因で登録解除処理が失敗した場合は、ActivationException
をスローします。 リモート呼出しが失敗した場合は、RemoteException
をスローします。
registerGroup
メソッドは、グループ記述子descで指定された起動グループを起動システムに登録し、そのグループに割り当てられたActivationGroupID
を返します。 オブジェクトを起動グループに登録する前に、その起動グループをActivationSystem
に登録しておく必要があります。 グループの登録が失敗した場合は、このメソッドはActivationException
をスローします。 リモート呼出しが失敗した場合は、RemoteException
をスローします。
activeGroup
メソッドは、ActivationGroup
からのコールバック(識別子idを伴う)であり、groupが現在アクティブな状態にあり、そのJVMのActivationInstantiator
になっていることを起動システムに知らせます。 このメソッドは、そのグループ内のグループまたはオブジェクトがアクティブでなくなったなど、オブジェクトとグループのステータスの変化をシステムに伝えるためにグループが使用するActivationMonitor
を取得するため、ActivationGroup.createGroup
メソッドにより内部的に呼び出されます。 指定されたグループが登録されていない場合は、メソッドはUnknownGroupException
をスローします。 指定されたグループがすでにアクティブな状態にある場合は、ActivationException
をスローします。 起動システムのリモート呼出しが失敗した場合は、RemoteException
をスローします。
unregisterGroup
メソッドは、指定された識別子id持つ起動グループを起動システムから削除します。 起動グループは、自分自身を破棄すべきであることをアクティベータに伝えるため、このコールバックを行います。 この呼出しが成功した場合は、そのグループにオブジェクトを登録したり、そのグループ内でオブジェクトを起動したりすることはできなくなります。 そのグループに関する情報と、そのグループに関連付けられたオブジェクトはすべてシステムから削除されます。 指定されたグループが登録されていない場合は、このメソッドはUnknownGroupException
をスローします。 リモート呼出しが失敗した場合は、RemoteException
をスローします。 データベースの更新の失敗などが原因で登録解除に失敗した場合は、ActivationException
をスローします。
shutdown
メソッドは、起動システムおよび関連するすべての起動プロセス(アクティベータ、モニター、グループ)を正常に(非同期に)終了させます。 起動デーモンにより生成されたすべてのグループは破棄され、起動デーモンは終了します。 起動システム・デーモンrmid
をシャットダウンするためには、次のコマンドを実行します。
rmid -stop [-port num]
このコマンドにより、指定されたポートで起動デーモンがシャットダウンされます。ポートを指定しない場合、デフォルト・ポート上のデーモンがシャットダウンされます。
7.4.3 ActivationMonitor
クラス
ActivationMonitor
はActivationGroup
に固有のクラスで、ActivationSystem.activeGroup
の呼び出し(ActivationGroup.createGroup
メソッドにより内部的に呼び出される)によりグループの報告が行われたときに取得されます。 次の場合には、起動グループは、ActivationMonitor
に報告する必要があります。
- そのオブジェクトがアクティブになり、
- オブジェクトが非アクティブになる、または
- グループ全体が非アクティブになります。
package java.rmi.activation;
public interface ActivationMonitor
extends java.rmi.Remote
{
public abstract void inactiveObject(ActivationID id)
throws UnknownObjectException, RemoteException;
public void activeObject(ActivationID id,
java.rmi.MarshalledObject mobj)
throws UnknownObjectException, java.rmi.RemoteException;
public void inactiveGroup(ActivationGroupID id,
long incarnation)
throws UnknownGroupException, java.rmi.RemoteException;
}
起動グループは、グループ内のオブジェクトが停止したときに、グループのモニターのinactiveObject
メソッドを呼び出します。 起動グループは、起動グループのinactiveObject
メソッドの呼出しにより、そのJVM内のオブジェクト(グループがその起動にかかわったオブジェクト)がアクティブでなくなったことを検出します。
inactiveObject
呼出しは、起動識別子idを持つオブジェクトを指すリモート・オブジェクト参照が有効でなくなったことをActivationMonitor
に知らせます。 モニターはidに関連した参照を無効な参照と見なします。 参照が無効と見なされるので、以後同じ起動識別子へのactivate
の呼出しでは、リモート・オブジェクトがふたたび起動されます。 指定されたオブジェクトがActivationMonitor
に認識されないオブジェクトである場合は、メソッドはUnknownObjectException
をスローします。 リモート呼出しが失敗した場合は、RemoteException
をスローします。
activeObject
は、idに関連付けられたオブジェクトが現在アクティブな状態にあることをActivationMonitor
に知らせます。 パラメータobjには、オブジェクトの整列化された形式のスタブを指定します。 ActivationGroup
は、グループ内のオブジェクトがシステムにより直接起動される以外の方法でアクティブになった場合(オブジェクトが自分自身で登録して「起動した」場合など)は、それをモニターに知らせなければなりません。 指定されたオブジェクトidが登録されていない場合は、メソッドはUnknownObjectException
をスローします。 リモート呼出しが失敗した場合は、RemoteException
をスローします。
inactiveGroup
は、idとincarnationで指定されたグループが現在アクティブでないことをモニターに知らせます。 グループ内のオブジェクトを起動する要求がそれ以降発生すると、グループはより大きな生成番号で再作成されます。 グループは、その中にあるすべてのオブジェクトが停止していると報告されると停止します。 指定されたグループidが登録されていないか、指定された生成番号がグループの現在の生成番号よりも小さい場合は、メソッドはUnknownGroupException
をスローします。 リモート呼出しが失敗した場合は、RemoteException
をスローします。
7.4.4 ActivationInstantiator
クラス
ActivationInstantiator
は、起動可能オブジェクトのインスタンスを生成する役割を持ちます。 ActivationGroup
の具象サブクラスでは、グループ内でのオブジェクトの作成を処理するためnewInstance
を実装しています。
package java.rmi.activation;
public interface ActivationInstantiator
extends java.rmi.Remote
{
public MarshalledObject newInstance(ActivationID id,
ActivationDesc desc)
throws ActivationException, java.rmi.RemoteException;
}
アクティベータは、起動識別子idと起動記述子descを持つオブジェクトをグループ内に再作成するため、インスタンシエータのnewInstance
メソッドを呼び出します。 インスタンシエータは、次の処理を行います。
- 記述子の
getClassName
メソッドを使って、オブジェクトのクラスを決定する getLocation
メソッドを使って起動記述子から取得したコードベース・パスから、そのクラスをロードする- オブジェクトのクラスの特別な「起動」コンストラクタを呼び出して、クラスのインスタンスを生成する。このコンストラクタは、
ActivationID
、およびオブジェクト固有の初期化データが格納されているMarshalledObject
の、2つの引数をとる - 作成したリモート・オブジェクトが含まれる
MarshalledObject
を返す。
また、インスタンシエータは、適切なinactiveObject
を呼び出せるように、作成または起動したオブジェクトがアクティブでなくなったことをそのActivationMonitor
に報告する役割も持ちます(詳細はActivationGroup
クラスを参照)。
オブジェクトの起動が失敗した場合は、newInstanceメソッドはActivationException
をスローします。 リモート呼出しが失敗した場合は、RemoteException
をスローします。
7.4.5 ActivationGroupDesc
クラス
起動グループ記述子(ActivationGroupDesc
)には、同じJVM内でオブジェクトを起動する起動グループを作成または再作成するのに必要な情報が含まれます。
次の情報が格納されています。
- グループのクラス名(クラス名が
null
の場合、デフォルトのActivationGroup
実装を表す) - グループのコードベース・パス(グループのクラスの場所)
- オブジェクト固有の初期化データが格納されている、「整列化された」オブジェクト。
グループのクラスは必ずActivationGroup
の具象サブクラスになります。 ActivationGroup
のサブクラスは、次の2つの引数をとる特別なコンストラクタを呼び出すstaticメソッドActivationGroup.createGroup
により作成または再作成されます。
- グループの
ActivationGroupID
- グループの初期化データ(
java.rmi.MarshalledObject
内)
package java.rmi.activation;
public final class ActivationGroupDesc
implements java.io.Serializable
{
public ActivationGroupDesc(java.util.Properties props,
CommandEnvironment env);;
public ActivationGroupDesc(String className,
String codebase,
java.rmi.MarshalledObject data,
java.util.Properties props,
CommandEnvironment env);
public String getClassName();
public String getLocation();
public java.rmi.MarshalledObject getData();
public CommandEnvironment getCommandEnvironment();
public java.util.Properties getPropertiesOverrides();
}
1つ目のコンストラクタは、グループの実装とコード位置としてシステムのデフォルト値を使用するグループ記述子を作成します。 プロパティは、Javaアプリケーション環境のオーバーライドを指定します(グループ実装のJVM内のシステム・プロパティをオーバーライドします)。 コマンド環境では、子JVMの起動に使用される正確なコマンドやオプションを制御するか、またはnull
を設定してrmid
のデフォルトを受け入れることが可能です。 このコンストラクタはnull
グループのクラス名を使ってActivationGroupDesc
を作成します。これはシステムのデフォルトであるActivationGroup
実装を示すものです。
2番目のコンストラクタは最初と同じですが、Properties
およびCommandEnvironment
を指定できるようになっています。
getClassName
メソッドは、グループのクラス名(null
の場合が多い)を返します。 null
グループのクラス名は、システムのデフォルトであるActivationGroup
実装を示します。
getLocation
メソッドは、グループのクラスのロード元となるコードベース・パスを返します。
getData
メソッドは、整列化された形式のグループの初期化データを返します。
getCommandEnvironment
メソッドは、コマンド環境(null
の場合が多い)を返します。
getPropertiesOverrides
メソッドは、この記述子のプロパティ・オーバーライド(null
の場合が多い)を返します。
7.4.6 ActivationGroupDesc.CommandEnvironment
クラス
CommandEnvironment
クラスを使用すると、デフォルトのシステム・プロパティのオーバーライド、および実装で定義されたActivationGroup
のオプション指定が可能になります。
public static class CommandEnvironment
implements java.io.Serializable
{
public CommandEnvironment(String cmdpath, String[] args);
public boolean equals(java.lang.Object);
public String[] getCommandOptions();
public String getCommandPath();
public int hashCode();
}
コンストラクタは、指定されたコマンド、cmdpath、および追加コマンド行オプションargsを使ってCommandEnvironment
を作成します。
equals
は、コマンド環境オブジェクトに等しい内容を実装します。 必要に応じてCommandEnvironment
がハッシュ・テーブルに格納されるように、hashCode
メソッドが適宜に実装されます。
getCommandOptions
メソッドは、環境オブジェクトのコマンド行オプションを返します。
getCommandPath
メソッドは、環境オブジェクトのコマンド文字列を返します。
7.4.7 ActivationGroupID
クラス
登録された起動グループの識別子は、次のような役割を持ちます。
- 起動システム内でグループを一意に識別する
- グループの起動システムへの参照を持つ。これにより、グループは必要に応じて、その起動システムに接続可能。
ActivationGroupID
は、ActivationSystem.registerGroup
を呼び出すことで取得でき、起動システム内でのグループの識別に使用されます。 このグループ識別子は、起動グループの作成または再作成時に、起動グループの特別なコンストラクタに引数として引き渡すことができます。
package java.rmi.activation;
public class ActivationGroupID implements java.io.Serializable
{
public ActivationGroupID(ActivationSystem system);
public ActivationSystem getSystem();
public boolean equals(Object obj);
public int hashCode();
}
ActivationGroupID
のコンストラクタは、ActivationSystemがsystemで指定された一意のグループ識別子を作成します。
getSystem
メソッドは、グループの起動システムを返します。
hashCode
メソッドは、グループの識別子のハッシュ・コードを返します。 同じリモート・グループを参照する2つのグループ識別子は、同じハッシュ・コードを持ちます。
equals
メソッドは、2つのグループ識別子を比較して、内容が等しいかどうかを調べます。 このメソッドは、1)一意の識別子が内容的に同一であり、なおかつ、2)それぞれの識別子で指定された起動システムが同一のリモート・オブジェクトを参照している場合は、true
を返します。
7.4.8 ActivationGroup
クラス
ActivationGroup
は、そのグループ内に起動可能オブジェクトの新しいインスタンスを生成し、次の場合にActivationMonitor
に通知します。
- そのオブジェクトがアクティブになり、
- オブジェクトが非アクティブになる、または
- グループ全体が非アクティブになります。
ActivationGroup
は最初、次のどれかの方法で作成します。
- オブジェクトの「デフォルト」の
ActivationDesc
作成の副作用として ActivationGroup.createGroup
メソッドを明示的に呼び出した場合ActivationGroupDesc
の登録のみが行われているグループ内の最初のオブジェクトを起動した副作用として
ActivationGroup
を再作成できるのはアクティベータだけです。 アクティベータは、登録されている起動グループごとに、必要に応じて独立したJVM (たとえば、子プロセスとして)を生成し、起動要求を適切なグループに転送します。 JVMをどのように生成するかは、実装に任せられます。 起動グループは、staticメソッドActivationGroup.createGroup
により作成します。 createGroup
メソッドには、作成するグループに関して、1)グループはActivationGroup
の具象サブクラスでなければならない、2)グループは次の2つの引数をとるコンストラクタを持っていなければならない、という決まりがあります。
- グループの
ActivationGroupID
- グループの初期化データ(
MarshalledObject
内)
作成時、ActivationGroup
のデフォルトの実装では、システム・プロパティはActivationGroupDesc
が作成されたときのシステム・プロパティ値に設定され、セキュリティ・マネージャはjava.rmi.RMISecurityManager
に設定されます。 グループ内でオブジェクトが起動されるときに、いくつかのプロパティについては独自の値を設定する場合は、任意のActivationDesc
が作成される前、つまり、デフォルトのActivationGroupDesc
が作成される前に設定するようにすべきです。
package java.rmi.activation;
public abstract class ActivationGroup
extends UnicastRemoteObject
implements ActivationInstantiator
{
protected ActivationGroup(ActivationGroupID groupID)
throws java.rmi.RemoteException;
public abstract MarshalledObject newInstance(ActivationID id,
ActivationDesc desc)
throws ActivationException, java.rmi.RemoteException;
public abstract boolean inactiveObject(ActivationID id)
throws ActivationException, UnknownObjectException,
java.rmi.RemoteException;
public static ActivationGroup createGroup(ActivationGroupID id,
ActivationGroupDesc desc,
long incarnation)
throws ActivationException;
public static ActivationGroupID currentGroupID();
public static void setSystem(ActivationSystem system)
throws ActivationException;
public static ActivationSystem getSystem()
throws ActivationException;
protected void activeObject(ActivationID id,
java.rmi.MarshalledObject mobj)
throws ActivationException, UnknownObjectException,
java.rmi.RemoteException;
protected void inactiveGroup()
throws UnknownGroupException, java.rmi.RemoteException;
}
アクティベータは、起動記述子descを持つオブジェクトを起動するため、起動グループのnewInstance
メソッドを呼び出します。 起動グループは、次のような役割を持ちます。
- 記述子の
getClassName
メソッドを使って、オブジェクトのクラスを決定する getLocation
メソッドを使って起動記述子から取得したURLから、そのクラスをロードする- オブジェクトの
ActivationID
と、オブジェクトの初期化データが含まれるMarshalledObject
の2つの引数をとるオブジェクトのクラスの特別なコンストラクタを呼び出して、そのクラスのインスタンスを生成する - 作成したリモート・オブジェクトを直列化したものをアクティベータに返す。
指定された記述子に対応するインスタンスを生成できなかった場合は、メソッドはActivationException
をスローします。
グループのinactiveObject
メソッドは、Activatable.inactive
メソッドの呼出しを介して間接的に呼び出されます。 リモート・オブジェクトの実装では、そのオブジェクトがアクティブでなくなったとき(アクティブでなくなったと見なされるとき)にActivatable
のinactive
メソッドを呼び出さなければなりません。 オブジェクトが終了時にActivatable.inactive
を呼び出さないと、グループは自身が作成したオブジェクトへの強参照を保持するので、オブジェクトは決してガベージ・コレクトされません。
グループのinactiveObject
メソッドは、リモート・オブジェクトがクライアントからのRMI呼出しに応じられないようにするため、idに関連付けられたリモート・オブジェクトをRMIランタイムからアンエクスポートします(リモート・オブジェクトに対する保留状態の呼び出しや実行中の呼出しがない場合に限る)。 オブジェクトへの保留状態の呼び出しや実行中の呼出しがある場合、inactiveObject
はfalse
を返し、アクションをとりません。
unexportObject
オペレーションが成功すると(オブジェクトには保留状態または実行中の呼出しがないことを意味する)、グループは、リモート・オブジェクトが現在アクティブでない状態にあり、したがって、それ以降の起動要求時にはアクティベータによって再度起動できることを、そのActivationMonitor
に知らせます(モニターのinactiveObject
を使用)。 オペレーションが成功すると、inactiveObject
はtrue
を返します。 ActivationGroup
によりオブジェクトがアクティブであると見なされる場合でも、すでにアンエクスポートされている場合は、このメソッドの呼出しは成功することがあります。
このオブジェクトがアクティブでないとすでに報告されている場合や、この起動グループで一度も起動されたことがないなどの理由から、起動グループがこのオブジェクトを知らない場合は、inactiveObject
メソッドはUnknownObjectException
をスローします。 アクティベータまたは起動グループのリモート呼出しが失敗するなどの非起動処理が失敗した場合は、RemoteException
をスローします。
createGroup
メソッドは、現在のJVM用に起動グループを作成し、設定を行います。 起動グループを設定できるのは、それが現在設定されていない場合だけです。 起動グループがcreateGroup
メソッドを使用して設定されるのは、着信するactivate
要求を実行するために、Activator
が起動グループの再作成を開始したときです。 グループをこのメソッドで作成する前には、グループ記述子をActivationSystem
に登録しておく必要があります(前の登録から得たActivationID
を渡す)。
ActivationGroupDesc
(desc)で指定するグループは、ActivationGroup
の具象サブクラスでなければならず、そのグループのActivationGroupID
と、そのグループの初期化データが含まれたMarshalledObject
(ActivationGroupDesc
から取得)の2つの引数を取るpublicコンストラクタを持っている必要があります。 ActivationGroupDesc.getClassName
メソッドがnull
を返す場合は、システムのデフォルト・グループ実装が使用されます。 ノート: 独自のカスタム起動グループを作成する場合は、グループのコンストラクタでセキュリティ・マネージャを設定する必要があります。コンストラクタ内にセキュリティ・マネージャを設定しないと、グループの中でオブジェクトを起動できません。
グループが作成されたら、グループのActivationMonitor
を返すactiveGroup
メソッドの呼出しによりグループがアクティブな状態になったことが、ActivationSystem
に知らされます。 このコールバックの処理はcreateGroup
メソッドが行うので、アプリケーション側で独自にactiveGroup
を呼び出す必要はありません。
グループが作成されると、それがアクティブでなくなるまでcurrentGroupID
メソッドによりこのグループの識別子が返されます。グループがアクティブでなくなると、currentGroupID
メソッドはnull
を返します。
パラメータincarnationは、グループの現在の生成番号(このグループが起動された回数を表す)を示します。 生成番号は、グループの作成に成功したあと、activeGroup
メソッドへのパラメータとして使用されます。 生成番号はゼロから始まります。 指定されたグループがすでに存在する場合、またはグループの作成中にエラーが発生した場合は、createGroup
メソッドはActivationException
をスローします。
setSystem
メソッドは、JVMのActivationSystem
(system)を設定します。 起動システムを設定できるのは、アクティブな状態のグループがない場合だけです。 setSystem
の明示的な呼出しにより起動システムが設定されなかった場合、getSystem
メソッドは、アクティベータのレジストリからjava.rmi.activation.ActivationSystemという名前を探すことでActivationSystem
への参照の取得を試みます。 デフォルトでは、起動システムの検索に使用されるポート番号は、ActivationSystem.SYSTEM_PORTで定義されています。 このポート定義は、プロパティjava.rmi.activation.portを設定することによりオーバーライドできます。 setSystem
メソッドを呼び出したときにすでに起動システムが設定されている場合は、メソッドはActivationException
をスローします。
getSystem
メソッドは、JVMの起動システムを返します。 起動システムはsetSystem
メソッドで設定できます(前述)。
activeObject
メソッドは、protectedメソッドで、サブクラスが、グループのモニターへのactiveObject
コールバックを行なって、指定された起動idを持ち、スタブがmobjに含まれるリモート・オブジェクトが現在アクティブな状態にあることをグループのモニターに知らせるために使用します。 この呼出しは、グループのActivationMonitor
にすぐに転送されます。
inactiveGroup
メソッドは、グループがアクティブでなくなったことをグループのモニターに知らせるため、サブクラスが使用するprotectedメソッドです。 サブクラスは、JVMの中でグループが起動にかかわっているオブジェクトがアクティブでなくなるたびに、このメソッドを呼び出します。
7.4.9 MarshalledObject
クラス
MarshalledObject
はオブジェクトのコンテナであり、RMI呼出しの際にオブジェクトをパラメータとして引き渡せるようにするものですが、受け取った側でのオブジェクトの直列化復元は、コンテナ・オブジェクトの呼出しを介してアプリケーションがそのオブジェクトを明示的に要求するまで延期されます。 MarshalledObject
に含まれるSerializable
オブジェクトは、RMI呼出しの際に引き渡されたパラメータと同じセマンティックスで、要求時に直列化および直列化復元されます。これは、MarshalledObject
内のすべてのリモート・オブジェクトが、そのスタブの直列化されたインスタンスによって表現されることを意味します。 MarshalledObject
に含まれるオブジェクトは、リモート・オブジェクト、非リモート・オブジェクト、リモート・オブジェクトと非リモート・オブジェクトのグラフ全体のいずれかになります。
オブジェクトがMarshalledObject
ラッパーの中に置かれると、直列化されたそのオブジェクトにコード・ベースURL (クラスのロード元)の情報が付加されます。同様に、MarshalledObject
ラッパーからオブジェクトが取り出されるときは、そのオブジェクトのコードがローカルになければ、直列化の際に付加されたURLから、そのオブジェクトのクラスのバイト・コードが特定されロードされます。
package java.rmi;
public final class MarshalledObject implements java.io.Serializable
{
public MarshalledObject(Object obj)
throws java.io.IOException;
public Object get()
throws java.io.IOException, ClassNotFoundException;
public int hashCode();
public boolean equals();
}
MarshalledObject
のコンストラクタは、引数として直列化可能なオブジェクトobjをとり、オブジェクトがバイト・ストリームに整列化された形式のものを保持します。 整列化された形式のオブジェクトは、次のように、RMI呼出しの際に引き渡されるオブジェクトのセマンティックスを保持します。
get
メソッドの呼出しによりオブジェクトが再構築されるときに、各クラスのバイト・コードを特定、ロードできるように、ストリーム中の各クラスには、そのコード・ベースURL情報が付加される- リモート・オブジェクトは、そのプロキシ・スタブで置き換えられる。
MarshalledObject
クラスのインスタンスがjava.io.ObjectOutputStream
に書き出されるときは、その中に含まれる整列化された形式のオブジェクト(構築時に作成されたもの)がストリームに書き出されます。したがって、バイト・ストリームだけが直列化されます。
MarshalledObject
がjava.io.ObjectInputStream
から読み出されるときは、その中に含まれるオブジェクトは具象オブジェクトに直列化復元はされません。整列化されたオブジェクトのget
メソッドが呼び出されるまで、オブジェクトは整列化された形式のままです。
get
メソッドは、常に、整列化された形式で含められているオブジェクトの新しいコピーを再構築します。 内部表現は、RMI呼出しの非整列化パラメータに対して使用されるセマンティックスで直列化復元されます。 したがって、オブジェクトの表現を直列化復元すると、直列化されたオブジェクトのストリームに埋め込まれたURL情報を使用してクラス・コードがロードされます(ローカルにない場合)。
整列化された形式のオブジェクトのhashCode
は、コンストラクタに引き渡されたオブジェクトと同じです。 equals
メソッドは、整列化された形式のオブジェクトどうしを比較し、それらが等価であればtrueを返します。 equalsが比較を実行する際、クラスのコード・ベース注釈は無視されます。これは、2つのオブジェクトが同じ直列化表現を保持する場合、それらは等価であることを意味します(直列化表現内の各クラスのコード・ベースを除く)。