目次||

2 分散オブジェクト・モデル


2.1 分散オブジェクト・アプリケーション

RMIアプリケーションは、多くの場合、サーバーとクライアントという2つのプログラムから構成されます。 一般的なサーバー・アプリケーションは、数多くのリモート・オブジェクトを作成し、それらのリモート・オブジェクトへの参照をアクセス可能にして、クライアントがそれらのリモート・オブジェクトのメソッドを呼び出すのを待ちます。 一般的なクライアント・アプリケーションは、サーバー内の1つまたは複数のリモート・オブジェクトへのリモート参照を取得し、それらのオブジェクトのメソッドを呼び出します。 RMIは、サーバーおよびクライアント間で通信や情報の受け渡しを行うメカニズムを提供します。 このようなアプリケーションは、分散オブジェクト・アプリケーションと呼ばれることがあります。

分散オブジェクト・アプリケーションで必要とされる処理は、次のとおりです。

次の図は、リモート・オブジェクトへの参照の取得にレジストリを使用するRMI分散アプリケーションを示しています。 サーバーは、リモート・オブジェクトに名前を関連付けるために、レジストリを呼び出します。 クライアントは、サーバーのレジストリ内の名前によってリモート・オブジェクトを見つけ、そのオブジェクトのメソッドを呼び出します。 この図は、RMIシステムで、既存のWebサーバーを使って、サーバーからクライアント、およびクライアントからサーバーに、必要に応じてオブジェクト用のJava言語内のクラスのバイト・コードをロードする様子も示しています。 RMIでは、Javaプラットフォームのサポートする任意のURLプロトコル(HTTP、FTP、ファイルなど)を使って、クラス・バイトコードがロードされます。

この図は、リモート・オブジェクトへの参照の取得にレジストリを使用するRMI分散アプリケーションを示しています。
この図は、レジストリを使用してリモート・オブジェクトへの参照を取得するRMI分散アプリケーションを示しています
.

2.2 用語の定義

Java SEプラットフォームの分散オブジェクト・モデルにおけるリモート・オブジェクトとは、別のJava仮想マシン(別のホスト上にある場合もある)からそのメソッドを呼び出すことができるオブジェクトです。 このタイプのオブジェクトは、リモート・オブジェクトのメソッドを宣言するJavaインタフェースである、1つまたは複数のリモート・インタフェースにより記述されます。

リモート・メソッド呼び出し (RMI)とは、リモート・オブジェクト上にあるリモート・インタフェースのメソッドを呼び出すアクションのことです。 この操作でもっとも重要なのは、リモート・オブジェクトを呼び出すための構文が、ローカル・オブジェクトのメソッド呼出しの場合と同じであることです。

2.3 分散モデルと非分散モデルの比較

Java SEプラットフォームの分散オブジェクト・モデルは、Java SEプラットフォームのオブジェクト・モデルと次の点でよく似ています。

Java SEプラットフォームの分散オブジェクトはJava SEプラットフォームのオブジェクト・モデルと次の点で異なります。

2.4 RMIインタフェースとクラスの概要

RMIシステムのリモート動作を決定するインタフェースとクラスは、java.rmiパッケージの階層で定義されます。 次の図は、このうちいくつかのインタフェースとクラスの関係を示します。

これらのインタフェースとクラスのいくつかの関係
これらのインタフェースとクラスのいくつかの関係

2.4.1 java.rmi.Remoteインタフェース

RMIにおいて、リモート・インタフェースは、リモートJava仮想マシンから呼び出される可能性があるメソッドのセットを宣言するインタフェースです。 リモート・インタフェースは、次の要件を満たしている必要があります。

java.rmi.Remoteインタフェースは、メソッドを定義しないマーカー・インタフェースです。

public interface Remote {}

リモート・インタフェースは、少なくともjava.rmi.Remoteインタフェース(またはjava.rmi.Remoteを継承する別のリモート・インタフェース)を継承する必要があります。 ただし、次の条件下では、リモート・インタフェースは、非リモート・インタフェースを継承する場合があります。

たとえば、次のインタフェースBankAccountは、銀行口座にアクセスするためのリモート・インタフェースを定義しています。 ここには、口座への預金、差引残高の取得、および口座からの引出しを行うためのリモート・メソッドが含まれています。

public interface BankAccount extends java.rmi.Remote {
        public void deposit(float amount)
                throws java.rmi.RemoteException;
        public void withdraw(float amount)
                throws OverdrawnException, java.rmi.RemoteException;
        public float getBalance()
                throws java.rmi.RemoteException;
}

次の例では、有効なリモート・インタフェースBetaは、リモート・メソッドおよびjava.rmi.Remoteインタフェースを持つ非リモート・インタフェースAlphaを継承しています。

public interface Alpha {
        public final String okay = "constants are okay too";
        public Object foo(Object obj)
                throws java.rmi.RemoteException;
        public void bar() throws java.io.IOException;
        public int baz() throws java.lang.Exception;
}

public interface Beta extends Alpha, java.rmi.Remote {
        public void ping() throws java.rmi.RemoteException;
}

2.4.2 RemoteExceptionクラス

java.rmi.RemoteExceptionクラスは、リモート・メソッド呼出しの間にRMIランタイムがスローする例外のスーパー・クラスです。 RMIシステムを使うアプリケーションの安定性を保つために、リモート・インタフェースで宣言される各リモート・メソッドはthrows節の中でjava.rmi.RemoteException (またはjava.io.IOExceptionjava.lang.Exceptionなどのjava.rmi.RemoteExceptionのスーパー・クラス)を指定する必要があります。

例外java.rmi.RemoteExceptionは、リモート・メソッド呼出しがなんらかの理由で失敗したときにスローされます。 リモート・メソッド呼出しは、次のような理由で失敗することがあります。

RemoteExceptionクラスは、チェック例外(リモート・メソッドの呼出し側が処理する必要があり、コンパイラによってチェックされる例外)で、RuntimeExceptionではありません。

2.4.3 RemoteObjectクラスとそのサブクラス

RMIサーバー関数はjava.rmi.server.RemoteObjectとそのサブクラス、java.rmi.server.RemoteServerjava.rmi.server.UnicastRemoteObject、およびjava.rmi.activation.Activatableが提供します。

2.5 リモート・インタフェースの実装

リモート・インタフェースを実装するクラスの一般的な規約は、次のとおりです。

たとえば、次に示すクラスBankAcctImplBankAccountリモート・インタフェースを実装し、java.rmi.server.UnicastRemoteObjectクラスを拡張しています。

package mypackage;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class BankAccountImpl
        extends UnicastRemoteObject
        implements BankAccount
{
        private float balance = 0.0;

        public BankAccountImpl(float initialBalance)
                throws RemoteException
        {
                balance = initialBalance;
        }
        public void deposit(float amount) throws RemoteException {
                ...
        }
        public void withdraw(float amount) throws OverdrawnException,
                RemoteException {
                ...
        }
        public float getBalance() throws RemoteException {
                ...
        }
}

注:

2.6 リモート・メソッド呼出しでのパラメータ引き渡し

リモート・オブジェクトへの引数、リモート・オブジェクトからの戻り値は、直列化可能なオブジェクトであればどれでも可能です。 これにはプリミティブ型、リモート・オブジェクト、java.io.Serializableインタフェースを実装した非リモート・オブジェクトが含まれます。 クラスを直列化可能にする方法の詳細については、Javaオブジェクト直列化仕様を参照してください。 ローカルでは入手できないパラメータまたは戻り値のクラスは、RMIシステムによって動的にダウンロードされます。 パラメータ、戻り値、および例外を読み込むときに、RMIがパラメータと戻り値のクラスをどのようにダウンロードするかの詳細については、"動的クラス・ロード"のセクションを参照してください。

2.6.1非リモート・オブジェクトの引き渡し

リモート・メソッド呼出しのパラメータとして渡されたり、リモート・メソッド呼出しの結果として戻される非リモート・オブジェクトは、コピーにより渡されます。つまり、非リモート・オブジェクトは、Java SEプラットフォームのオブジェクト直列化メカニズムを使って直列化できます。

したがって、リモート・メソッド呼出しで非リモート・オブジェクトが返されるとき、非リモート・オブジェクトの内容は、リモート・オブジェクトの呼出しが呼び出される前にコピーされます。

リモート・メソッド呼び出しから非リモート・オブジェクトが戻されるときは、呼出し側の仮想マシンに新規オブジェクトが作成されます。

2.6.2リモート・オブジェクトの引き渡し

リモート・メソッド呼出しで、エクスポートされたリモート・オブジェクトをパラメータまたは戻り値として渡す場合には、そのリモート・オブジェクトのスタブが代わりに渡されます。 エクスポートされていないリモート・オブジェクトは、スタブ・インスタンスに置き換えられません。 パラメータとして渡されたリモート・オブジェクトは、リモート・インタフェースだけを実装できます。

2.6.3 参照整合性

単一のリモート・メソッド呼出しで、あるオブジェクトへの2つの参照が、あるJVMから別のJVMへパラメータ(または戻り値)として渡され、それらの参照が送信側のJVM上の同一オブジェクトを参照している場合、これらの参照は、受信側のJVM上のオブジェクトの1つのコピーも参照します。 さらに一般的に説明すると、単一のリモート・メソッド呼出し内では、RMIシステムは、呼出し内でパラメータとして渡されたり、戻り値として返されるオブジェクト間の参照の整合性を維持します。

2.6.4クラスの注釈

リモート・メソッド呼出しで、あるJVMから別のJVMにオブジェクトを送信する際に、RMIシステムは呼出しストリーム内のクラス記述子にクラスの情報(URL)を注釈として付け、受信側でクラスをロードできるようにします。 リモート・メソッド呼出し中には、必要に応じて随時、クラスをダウンロードする必要があります。

2.6.5パラメータの転送

リモート呼出し先に渡すパラメータを直列化するために、RMI呼出し内のパラメータは、java.io.ObjectOutputStreamクラスのサブクラスであるストリームに書き込まれます。 ObjectOutputStreamサブクラスは、replaceObjectメソッドをオーバーライドして、エクスポートされた各リモート・オブジェクトを対応するスタブ・インスタンスで置き換えます。 オブジェクトであるパラメータは、ObjectOutputStreamwriteObjectメソッドを使ってストリームに書き込まれます。 ObjectOutputStreamは、writeObjectメソッドによってストリームに書き込まれた各オブジェクト(書き込まれたオブジェクトによって参照されているオブジェクトも含む)の、replaceObjectメソッドを呼び出します。 RMIのサブクラスObjectOutputStreamreplaceObjectメソッドの戻り値は、次のとおりです。

RMIのサブクラスObjectOutputStreamannotateClassメソッドを実装し、クラスが呼出し側でダウンロードできるように呼出しストリームにクラスの場所についての注釈を付けます。 annotateClassの使用方法の詳細については、"動的クラス・ロード"セクションを参照してください。

どのパラメータも同一のObjectOutputStreamに書き込まれるため、呼出し側で同じオブジェクトを参照している参照は、受信側でも同じオブジェクトのコピーを参照します。 受信側では、パラメータは同一のObjectInputStreamによって読み取られます。

オブジェクトの書込み用のObjectOutputStream (および読取り用のObjectInputStream)のその他のデフォルトの動作は、パラメータの引き渡しで維持されます。 たとえば、オブジェクトの書込み時のwriteReplaceの呼び出し、およびオブジェクトの読取り時のreadResolveの呼出しは、RMIのパラメータ整列化および非整列化ストリームで優先されます。

戻り値(または例外)も上記のRMIでのパラメータの引き渡しと同じ方法でObjectOutputStreamサブクラスに書き込まれ、パラメータの転送と同じ方法で置き換えられます。

2.7リモート・オブジェクトの位置決め

単純ブートストラップ・ネーム・サーバーがリモート・オブジェクトに対する名前付き参照を保存するために準備されています。 リモート・オブジェクト参照は、java.rmi.NamingクラスのURLをベースとするメソッドを使って保存できます。

クライアントがリモート・オブジェクトのメソッドを呼び出すときには、クライアントはまずそのオブジェクトに対する参照を取得する必要があります。 リモート・オブジェクトに対する参照は通常、メソッド呼出しのパラメータまたは戻り値として得られます。 RMIシステムは単純ブートストラップ・ネーム・サーバーを提供して指定されたホストのリモート・オブジェクトを得られるようにしています。 java.rmi.Namingクラスは、URL (Uniform Resource Locator)ベースのメソッドを提供して特定のホストとポートにおける名前とオブジェクトのペアのルックアップ、バインド、リバインド、アンバインドおよびリストを可能にしています。


Copyright © 1997, 2017, Oracle and/or its affiliates. All rights reserved.

目次||