目次 | 前の項目 | 次の項目 | Java Remote Method Invocation |
起動識別子を介してアクセスできるリモートオブジェクトを作成するには、次のことを行う必要があります。
起動記述子 (ActivationDesc) は、次のどれかの方法で登録できます。
起動が行えるようにオブジェクトを登録するときは、上の方法のどれか 1 つだけを使用してください。複数の方法を使用しないでください。起動可能オブジェクトの実装方法の例については、後述する「起動可能リモートオブジェクトの構築」を参照してください。
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 であるオブジェクトのオブジェクト記述子を構築します。この形式のコンストラクタが使用される場合、オブジェクトのグループ識別子は、デフォルトでその VM の ActivationGroup の現在の識別子になります。同じ ActivationGroupID を持つオブジェクトは、すべて同じ VM 内で起動されます。現在のグループがアクティブでない場合、またはデフォルトグループが作成できない場合は、ActivationException がスローされます。groupID が null の場合は、IllegalArgumentException がスローされます。
注 - その VM の ActivationGroup が現在アクティブでない場合は、ActivationGroup 作成の副作用としてデフォルトの ActivationGroup が作成されます。デフォルトの起動グループは、セキュリティマネージャとして java.rmi.RMISecurityManager を使用し、再起動の際は、起動されたグループの VM のプロパティを、その VM の現在のプロパティに設定します。別のセキュリティマネージャが必要な場合は、デフォルトの ActivationDesc を作成する前に VM の起動グループを設定する必要があります。VM の ActivationGroup を作成する方法の詳細は、ActivationGroup.createGroup メソッドを参照してください。
ActivationDesc の 2 つ目のコンストラクタは、1 つ目のコンストラクタと同じようにしてオブジェクト記述子を構築しますが、パラメータ restart も指定する必要があります。オブジェクトの「再起動サービス」を必要とする場合、つまり、アクティベータの再起動時にオブジェクトが自動的に再起動されるようにするには (必要なときに 遅延起動するのとは反対)、restart に true を指定します。restart に false を指定すると、オブジェクトは必要なときにリモートメソッド呼び出しにより起動されます。ActivationDesc の 3 つ目のコンストラクタは、グループ識別子が groupID で、codebase で指定されたコードベースパスからロードできるクラス className、および初期化情報が data であるオブジェクトのオブジェクト記述子を構築します。同じ groupID を持つオブジェクトは、すべて同じ Java VM 内で起動されます。
ActivationDesc の 4 つ目のコンストラクタは、3 つ目のコンストラクタと同じようにしてオブジェクト記述子を構築しますが、再起動モードを指定できるようになっています。前述したオブジェクトの再起動サービスが必要な場合は、restart に true を指定します。
getGroupID
メソッドは、記述子で指定されたオブジェクトのグループ識別子を返します。グループは、複数のオブジェクトを 1 つの Java Virtual Machine にまとめる役割を果たします。
getClassName
メソッドは、起動記述子で指定されたオブジェクトのクラス名を返します。
getLocation
メソッドは、オブジェクトのクラスのダウンロード元となるコードベースパスを返します。
getData
メソッドは、記述子で指定されたオブジェクトの初期化 (起動) データが含まれる「整列化されたオブジェクト」を返します。
getRestartMode
メソッドは、このオブジェクトの再起動モードが有効になっている場合は true を返し、無効になっている場合は false を返します。
起動プロトコルでは、起動可能なリモートオブジェクトを起動識別子により表します。起動識別子 (ActivationID クラスのインスタンス) には、オブジェクトを起動するために必要な次のような情報が含まれています。
オブジェクトの起動識別子は、オブジェクトを起動システムに登録することで取得できます。登録は次のような方法で行えます (前述の内容にも留意のこと)。
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 がスローされます。オブジェクト識別子がアクティベータが知らない識別子である場合、activate
メソッドは UnknownObjectException をスローします。アクティベータのリモート呼び出しが失敗した場合は、RemoteException がスローされます。
equals
メソッドは、内容が等しいかどうかをチェックするメソッドです。このメソッドは、すべてのフィールドが等価 (各フィールドのObject.equals
のセマンティクスに照らし合わせて同一または等価) である場合は true を返します。p1 と p2 が ActivationID クラスのインスタンスであるとすると、p1.equals(p2)
が true を返す場合は、hashCode
メソッドは同じ値を返します。
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 クラスを extends 節で拡張していてもしていなくてもかまいません。Activatable クラスを拡張した場合、リモートオブジェクトの実装には、スーパークラス java.rmi.server.RemoteObject から適切なhashCode
メソッドと equals メソッドの定義が継承されます。したがって、同一の Activatable リモートオブジェクトを参照するリモートオブジェクト参照が 2 つある場合、この 2 つの参照は等価になります (equals
メソッドが true を返す)。また、Activatable
クラスのインスタンスは、その適切なスタブオブジェクトと等しくなります。たとえば、Object.equals
メソッドを、その引数にオブジェクトの実装に対応するスタブオブジェクトを指定して呼び出すと、true が返されます (逆の場合も同様)。
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 クラスの具体的なサブクラスから呼び出さなければなりません。
構築の副作用として、リモートオブジェクトは指定されたポート port で RMI ランタイムに「エクスポート」され、クライアントからの呼び出しに応じられるようになります。このコンストラクタは、RMI ランタイムへのオブジェクトのエクスポートが失敗した場合は RemoteException をスローします。4 つ目のコンストラクタは 3 つ目のコンストラクタと同じですが、この起動可能オブジェクトとのやりとりに使用するクライアントソケットファクトリとサーバソケットファクトリを指定できるようになっています。
getID
メソッドは、オブジェクトの起動識別子を返します。このメソッドは、サブクラスだけがオブジェクトの識別子を取得できるように protected 指定されています。オブジェクトの識別子は、オブジェクトがアクティブでないことを報告する場合、またはオブジェクトの起動記述子の登録を解除する場合に使用します。
register
メソッドは、起動可能リモートオブジェクトを必要なときに起動できるように、そのオブジェクト記述子 desc を起動システムに登録します。このメソッドを使用するのは、起動可能オブジェクトを、事前に作成しないで登録するときです。このメソッドは、起動可能オブジェクトをあとで保存したり呼び出したりできるように、その Remote スタブを返します。この結果、起動可能オブジェクトは、はじめに強制的に作成または起動されます。desc のグループ識別子が起動システムに登録されていない場合は、このメソッドは UnknownGroupException をスローします。起動システムが動作していない場合は ActivationException をスローします。また、起動システムのリモート呼び出しが失敗した場合は RemoteException をスローします。
inactive
メソッドは、指定した起動 id を持つオブジェクトが現在アクティブでないことをシステムに知らせるために使用します。現時点でアクティブとされているオブジェクトは、クライアントからの呼び出しを受けないように RMI ランタイムからアンエクスポートされます (保留状態の呼び出しや実行中の呼び出しがない場合だけ)。また、このメソッドを呼び出すと、この VM の ActivationGroup にもオブジェクトがアクティブでないことが知らされ、これを受けて、ActivationGroup は、その ActivationMonitor にオブジェクトがアクティブでないことを知らせます。このメソッドの呼び出しが成功した場合、それ以降、アクティベータに対して起動要求があると、オブジェクトは再度起動されます。inactive
メソッドは、オブジェクトのアンエクスポートに成功した場合、つまり、保留状態の呼び出しや実行中の呼び出しがない場合は true を返し、保留状態の呼び出しや実行中の呼び出しが存在するためにオブジェクトをアンエクスポートできなかった場合は false を返します。指定したオブジェクトがアクティベータが知らないオブジェクトである場合、このメソッドは UnknownObjectException をスローします (すでにアクティブでなくなっている可能性あり)。グループがアクティブでない場合は ActivationException をスローします。モニタにオブジェクトがアクティブでないことを知らせるのに失敗した場合は RemoteException をスローします。オブジェクトがアクティブであると見られる場合であっても、すでにアンエクスポートされている場合は、このメソッドの呼び出しは成功することがあります。
unregister
メソッドは、id に関連付けられた起動記述子の登録を解除します。この結果、オブジェクトはその id で起動できなくなります。オブジェクト id が起動システムが知らない識別子である場合は、UnknownObjectException がスローされます。起動システムが動作していない場合は、ActivationException がスローされます。起動システムのリモート呼び出しが失敗した場合は、RemoteException がスローされます。1 つ目の
exportObject
メソッドは、extends 節で Activatable クラスを拡張していない「起動可能」オブジェクトから明示的に呼び出すことができます。このメソッドは、a) オブジェクトを起動できるように、指定された codebase と data から構築されたオブジェクトの起動記述子 desc を起動システムに登録する、b) リモートオブジェクト obj を特定のポート port でエクスポートする (port にゼロを指定した場合は匿名ポートが選ばれる)、という 2 つの目的に使用します。エクスポートされたオブジェクトは、RMI 呼び出しを受け取ることができるようになります。この
exportObject
メソッドは、起動記述子 desc を起動システムに登録することで得た起動識別子を返します。起動グループが VM でアクティブになっていない場合は、ActivationException がスローされます。オブジェクトの登録またはエクスポートが失敗した場合は、RemoteException がスローされます。obj が extends 節で Activatable を拡張している場合は、Activatable の 1 つ目のコンストラクタがこのメソッドを呼び出すため、このメソッドを呼び出す必要はありません。
2 つ目の
exportObject
メソッドは、1 つ目のexportObject
メソッドと同じですが、起動可能オブジェクトとのやりとりに使用するクライアントソケットファクトリとサーバソケットファクトリを指定できるようになっています。3 つ目の
exportObject
メソッドは、識別子 id を持つ「起動可能」リモートオブジェクト (必ずしも Activatable 型である必要はない) を RMI ランタイムにエクスポートし、オブジェクト obj がクライアントからの呼び出しに応じられるようにします。port にゼロを指定した場合は、オブジェクトは匿名ポートでエクスポートされます。起動中、この
exportObject
メソッドは、extend 節で Activatable クラスを拡張していない「起動可能」オブジェクトから明示的に呼び出すようにすべきです。Activatable クラスを拡張しているオブジェクトの場合は、このメソッドを直接呼び出す必要はありません。この場合、このメソッドは上の 3 つ目のコンストラクタ (サブクラスがその特別な起動コンストラクタから呼び出すコンストラクタ) により呼び出されます。この
exportObject
メソッドは、起動可能オブジェクトの Remote スタブを返します。オブジェクトのエクスポートに失敗した場合は、このメソッドは RemoteException をスローします。4 つ目の exportObject メソッドは 3 つ目の exportObject メソッドと同じですが、この起動可能オブジェクトとのやりとりに使用するクライアントソケットファクトリとサーバソケットファクトリを指定できるようになっています。
unexportObject
メソッドは、リモートオブジェクト obj をクライアントからの呼び出しに応じられないようにします。force パラメータに true を指定すると、保留状態のリモートオブジェクト呼び出しが存在する場合や、リモートオブジェクトの呼び出しが実行中の場合であっても、オブジェクトは強制的にアンエクスポートされます。force パラメータに false を指定すると、保留状態の呼び出しや実行中の呼び出しがない場合に限り、オブジェクトはアンエクスポートされます。オブジェクトのアンエクスポートに成功した場合、RMI ランタイムはその内部テーブルからそのオブジェクトを削除します。RMI から強制的にオブジェクトを削除すると、クライアントはそのリモートオブジェクトへの古い参照を保持したままになってしまう可能性があります。指定したオブジェクトが RMI ランタイムにエクスポートされていない場合は、このメソッドは java.rmi.NoSuchObjectException をスローします。
オブジェクトを起動できるようにするには、「起動可能」オブジェクトの実装クラス (Activatable クラスを拡張しているかどうかにかかわらず) で、その起動識別子 (ActivationID 型のもの) と、その起動データ java.rmi.MarshalledObject (登録時に使用した起動識別子で提供したもの) の 2 つの引数をとる特別な public コンストラクタを定義する必要があります。起動グループは、その VM 内でリモートオブジェクトを起動するときに、この特別なコンストラクタを使用してリモートオブジェクトを構築します (詳細は後述)。リモートオブジェクトの実装では、適切な方法により自分自身を初期化するために、起動データが使用される可能性があります。また、Activatable.inactive
メソッドによりアクティブでなくなったときに起動グループにそれを知らせることができるように、リモートオブジェクトで、その起動識別子を保持しておくこともできます。Activatable の 1 つ目と 2 つ目のコンストラクタは、起動可能オブジェクトの登録と、指定されたポート port でのオブジェクトのエクスポートの両方に使用されます。このコンストラクタは、オブジェクトを最初に構築するときに使用すべきです。3 つ目のコンストラクタは、オブジェクトを再度起動するときに使用します。
Activatable の具体的なサブクラスでは、最初の構築時には 1 つ目または 2 つ目のコンストラクタを呼び出して、オブジェクトの登録とエクスポートを行う必要があります。このコンストラクタは、まず、オブジェクトのクラス名、オブジェクト用に提供された codebase および data により起動記述子 (ActivationDesc) を作成します。また、その起動グループは VM のデフォルトのグループになります。次に、作成した起動記述子をデフォルトの ActivationSystem に登録します。最後に、起動可能オブジェクトを特定のポート port で RMI ランタイムにエクスポートし (port にゼロを指定した場合は匿名ポートが選ばれる)、オブジェクトを
activeObject
としてローカルな ActivationGroup に報告します。登録中かエクスポート中にエラーが発生した場合は、このコンストラクタは RemoteException をスローします。なお、それ以降、protected メソッドgetID
を呼び出すとオブジェクトの起動識別子が返されるように、オブジェクトの ActivationID (登録により取得したもの) の初期化も行います。Activatable の 3 つ目のコンストラクタは、指定されたポートでのオブジェクトのエクスポートに使用されます。この 3 つ目のコンストラクタは、オブジェクト自身が次の 2 つの引数をとるオブジェクト自身の「起動」コンストラクタにより起動されるときに Activatable クラスの具体的なサブクラスから呼び出さなければなりません。
このコンストラクタは、起動可能オブジェクトを特定のポート port で RMI ランタイムにエクスポート (port にゼロを指定した場合は匿名ポートが選ばれる) するだけで、オブジェクトがアクティブであることを ActivationGroup に知らせることはしません。これは、この 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 ランタイムに「エクスポート」する処理を行います。したがって、extends 節で Activatable クラスを拡張しているオブジェクトの実装では、適切なスーパークラスのコンストラクタを呼び出す場合を除いて、オブジェクトを明示的にエクスポートする必要はありません。extends 節で Activatable クラスを拡張していないオブジェクトの実装では、static メソッドActivatable.exportObject
のどれかを呼び出してオブジェクトを明示的にエクスポートしなければなりません。次の例では、ServerImpl は Activatable ではなく別のクラスを extends 節で拡張しています。したがって、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 を実装したオブジェクトをとるメソッドにパラメータとして渡すことができます。