目次 前項目 次項目

システムアーキテクチャ


トピックス:

概要

RMI システムはスタブ/スケルトン層リモート参照層トランスポート層の3つの層から構成されます。各層の境界は特定のインタフェースとプロトコルで定義され、それぞれの層は隣接する層とは独立に存在し、システムの他の層に影響を及ぼすことなしに別の実装と入れ替えることも可能です。例えば、現在のトランスポート層は TCP-ベース(Java socketsを使用)の実装ですが、これを UDP ベースのトランスポートへ入れ替えることも可能です。

オブジェクトを一つのアドレス空間から他のアドレス空間へユーザから見て透過的な方法で伝達するために、オブジェクト直列化(Java 言語に特有の設計です)という技術が使われます。 オブジェクト直列化についてはこの章ではプリミティブとオブジェクトの整列化に関連した部分のみを説明します。更に完全な内容についてはオブジェクト直列化仕様を参照してください。

ダイナミックスタブローディングという別な技術により、クライアント側のスタブがリモートオブジェクト自体と同じリモートインタフェースを実装することが可能になります。 この技術は、クライアント側で厳密な型のスタブがまだ利用できないときに、クライアントが型キャストと型チェックのために Java 言語の組み込み演算子を使えるようにします。

アーキテクチャの概要

RMI システムは3つの層から構成されます。

アプリケーション層は RMI システムの上に存在します。次の図が層の相互関係を示します。

クライアントからのリモートサーバオブジェクトへのリモートメソッド呼び出しは、クライアント側の RMI システムを下に降りてトランスポートへ達し、次にサーバ側のトランスポートから上へ伝わってサーバに達します。

リモートサーバオブジェクト上のメソッドを呼び出すクライアントは実際にはリモートオブジェクトのスタブまたはプロキシをリモートオブジェクトへの通路として利用します。クライアント側が持っているリモートオブジェクトへの参照はローカルスタブへの参照です。 このスタブはリモートオブジェクトのリモートインタフェースの実装であり、リモート参照層を経由して、サーバオブジェクトへ呼び出し要求を転送します。 スタブは rmic コンパイラにより生成されます。

リモート参照層 は呼び出しの意味解析を司ります。例えば、サーバが単一のオブジェクトなのか、あるいは複製オブジェクトで複数のロケーションとの通信が必要なのかを決定するのはリモート参照層の仕事になります。 リモートオブジェクトの実装はそれぞれが自分のリモート参照セマンティクスを選択します −サーバが単一オブジェクトなのか、あるいは自分自身の複製との通信を必要とする複製オブジェクトなのかを選択します。

サーバへの参照のセマンティクスもリモート参照層が取り扱います。 例えば、リモート参照層はオブジェクト参照方法の違いを抽出して、(a) そのサーバはあるマシン上で常時実行されているのか、(b) そのサーバはメソッド呼び出しが起こったときだけ活性化されて実行する実装になっているのかを判定します。 リモート参照層の上に位置する層からはこれらの差を認識することができません。

トランスポート層 は接続のセットアップ、接続管理、そしてトランスポートのアドレス空間にあるリモートオブジェクト(リモート呼び出しのターゲット)のトラッキングとディスパッチを司ります

リモートオブジェクトへのディスパッチのために、トランスポートはリモート呼び出しをその上にあるリモート参照層に伝えます。リモート参照層は要求をサーバ側スケルトンに渡す前にサーバ側が必要とする動作をすべて取り扱います。 リモートオブジェクトのスケルトンは、実際のメソッド呼出しを実行するリモートオブジェクトの実装への呼び出しを作成します。

呼び出しに対する返り値はスケルトンを通ってリモート参照層へ伝えられ、サーバ側のトランスポートへ伝えられ、次にトランスポートを通過して上に進みリモート参照層を通ってクライアント側のスタブに到達します。

スタブ/スケルトン層

スタブ/スケルトン層はアプリケーション層と他の RMI システムとのインタフェースです。この層はトランスポートの詳細を取り扱うものではありませんが、marshal ストリームでの抽象化を介してデータをリモート参照層へ送ります。 marshal ストリームはオブジェクト直列化という機構によりアドレス空間内での Java オブジェクトの伝送を可能にします。 オブジェクト直列化システムを使って伝送されたオブジェクトは、それがリモートオブジェクトでなければ、リモートアドレス空間へコピー渡しされます。もしリモートオブジェクトであれば参照渡しされます。

リモートオブジェクトへのスタブとはリモートオブジェクトへのクライアント側のプロキシです。 このようなスタブはリモートオブジェクトの実装がサポートするすべてのインタフェースを備えています。 クライアント側のスタブは次の役目を果たします。

リモートオブジェクトの スケルトンは実際のリモートオブジェクトの実装に対して呼び出しを割り当てるメソッドを含んだサーバ側のコンポーネントです。 スケルトンは次の役目を果たします。

どのスタブまたはスケルトンクラスを使うかは実行時に決定され、必要に応じて動的にロードされます。詳細は ダイナミッククラスローディングで解説されます。 スタブとスケルトンは rmic コンパイラにより生成されます。

リモート参照層

リモート参照層はより低いレベルでのトランスポートインタフェースを扱います。この層はクライアントスタブとサーバスケルトンから独立した、特定のリモート参照プロトコルの実行についても責任を持ちます。

それぞれのリモートオブジェクトの実装は自分用のリモート参照サブクラスを選択します。この層では、次に示す例のように種々の呼び出しプロトコルが実行可能です。

リモート参照層はクライアント側とサーバ側のコンポーネントという2つの協調して働くコンポーネントを持ちます。クライアント側のコンポーネントはリモートサーバ(リモート参照が複製オブジェクトに対してならば複数のサーバ)に特有な情報を持っており、トランスポートを介してサーバ側のコンポーネントと交信します。 各メソッド呼び出しの期間中に、クライアントとサーバ側のコンポーネントは特定のリモート参照セマンティクスを実行します。例えば、リモートオブジェクトが複製オブジェクトの一部であるならば、クライアント側のコンポーネントは呼び出しを単一のリモートオブジェクトだけにではなくそれぞれの複製に呼び出しを転送します。

同じような方法で、サーバ側コンポーネントは、スケルトンにリモートメソッド呼び出しを伝達するのに先立ち、特定のリモート参照セマンティクスを実装します。このコンポーネントは例えば、複製グループの他のサーバと交信しながら強力なマルチキャストデリバリーを取り扱います(マルチキャストデリバリは JDK 1.1 リリースの RMI には含まれないことに注意)。

リモート参照層はストリーム指向接続の abstraction を介してトランスポート層への伝達を行います。接続実装の詳細はトランスポートが取り扱います。 接続はストリームをベースとするインタフェースを表しますが、その抽象化の下では接続のないトランスポートを実装することも可能です。

トランスポート層

一般的には、RMI のトランスポート層は次の項目に対して責任を負います。

リモートオブジェクト参照の具体的な表現はエンドポイントとオブジェクト識別子で構成されます。この表現を live reference と呼びます。 リモートオブジェクトへの live reference を与えらたならば、トランスポートはエンドポイントを使ってリモートオブジェクトが存在するアドレス空間への接続セットアップが可能になります。サーバ側では、トランスポートはオブジェクト識別子を使ってリモート呼び出しの対象をさがすことができます。

RMI システムのトランスポートは4つの基本的な abstraction から構成されます。

エンドポイントが具体的に何を表現するかはトランスポートが定義します。従って、トランスポートの多重実装もあり得ます。 設計と実装によっては一つのアドレス空間への多重トランスポートはサポート可能であり、同じ仮想マシン内で TCP と UDP 両方をサポートすることもできます。ただし、RMI トランスポートインタフェースは仮想マシンの実装において利用可能であり、直接アプリケーションからは利用できないことに注意してください。

リモートメソッド呼び出しにおけるスレッドの使用法

RMI ランタイムがリモートオブジェクトの実装(サーバ)へメソッドをディスパッチすると、そのメソッドは別なスレッドで実行される場合とそうでない場合が出てきます。同一のクライアント仮想マシンから発生した呼び出しのうちの幾つかが同一のスレッド内で実行され、また幾つかは他のスレッドで実行されます。 異なるクライアント仮想マシンから発生した呼び出しはそれぞれ異なるスレッドで実行されます。最後に説明した異なるクライアント仮想マシンのケースを除くと、RMI ランタイムはリモートオブジェクト呼び出しとスレッドのマッピングに対して何の保証も行いません。

リモートオブジェクトのガベージコレクション

ローカルシステムにおけるのと同様に、分散システムにおいても、どのクライアントからも参照されなくなったリモートオブジェクトは自動的に削除されるのが望ましいことです。 これによりプログラマはリモートオブジェクトのクライアントを追跡して、適切な時期にリモートオブジェクトを終了させるという仕事から解放されます。RMI は参照をカウントする方式の、Modula-3 の Network Objects に似たガベージコレクションアルゴリズムを採用しています。( Birrell, Nelson, Owickiによる次の文献を参照。"Network Objects" Digital Equipment Corporation Systems Research Center Technical Report 115, 1994.)

参照カウント式ガベージコレクションを実行するために、RMI のランタイムは各 Java 仮想マシン内で生き残っている参照を常に監視しています。 生きた参照が Java 仮想マシンに入ってくると参照カウントは増加します。あるオブジェクトへの最初の参照は「参照が起こった」というメッセージをそのオブジェクトのサーバへ送ります。生きた参照がローカルな仮想マシン内で参照されていないことが分かると、ファイナライズされてカウントは減少します。最後の参照が廃棄されると、「参照されていない」というメッセージがサーバに送られます。このプロトコルには微妙な点が数多くありますが、それらは大部分参照と非参照メッセージの順序を正しく管理してオブジェクトが不必要に回収されるのを防ぐことを保証します。

リモートオブジェクトがどのクライアントからも参照されていない状態になると、RMIランタイムは、そのオブジェクトを弱い参照(weak reference)によって参照します。 弱い参照になると Java 仮想マシンのガベージコレクタは、もしそのオブジェクトへのローカル参照が他に存在しなければ、オブジェクトは廃棄します。分散ガベージコレクションアルゴリズムは、オブジェクトへのノーマルな参照と弱い参照を保持しながら、ローカル Java 仮想マシンのガベージコレクタと相互作用を続けます。 通常のオブジェクトのライブサイクルと同様に、ガベージコレクタがそのオブジェクトへの参照はもはや存在しないと判断すると finalize が呼び出されます。

リモートオブジェクトへのローカルな参照が存在している間はガベージコレクトされることはなく、オブジェクトはリモート呼び出しに渡されたり、クライアントに返されたりします。リモートオブジェクトを渡すと、それが渡された仮想マシンの識別子が参照セットへ追加書き込みされます。 非参照の通知を必要とするリモートオブジェクトは java.rmi.server.Unreferenced インタフェースを実装しなければなりません。これらの参照が存在しなくなると unreferenced メソッドが呼び出されます。 unreferenced は参照セットが空であると呼び出されますから、このメソッドは複数回呼び出されることがあります。リモートオブジェクトが回収されるのは、リモートとローカルを含めて参照が全く無くなった場合だけです。

もし、クライアントとリモートサーバの間にネットワークパーティションが存在すると、リモートオブジェクトのコレクションが早すぎる時期に起こり得ます (トランスポートがクライアントがクラッシュしたと判断するかもしれないからです)。 時期尚早な回収の可能性があるため、リモート参照は参照に関する完全な整合性を保証するものではありません。別な言葉で言えば、リモート参照が実際に存在するオブジェクトを参照していない可能性が常に存在するということです。対象を持たない参照を使おうとすると RemoteException が発生し、その取り扱いはアプリケーションが行わなければなりません。

クラスのダイナミックローディング

RPC (remote procedure call) システムでは、リモートプロシージャ呼び出しが起こる前に、クライアント側のスタブコードが作成されてクライアントにリンクされている必要があります。このコードは静的にクライアントにリンクされる場合と、ローカルまたはネットワークファイルシステムに存在するライブラリの動的リンクによりランタイムにリンクされる場合があります。どちらの場合であっても、RPC を取り扱う特定のコードはコンパイルされた形態でクライアントマシンから利用できなければなりません。

RMI はこのテクニックを一般化し、動的クラスローディングと呼ばれるメカニズムによりリモートオブジェクトのメソッド呼び出しに必要なクラスを(Java言語のアーキテクチャでいうところのニュートラルなバイトコードとして)ランタイムにローディングします。 これらのクラスは:

この章では次の内容を説明します。

クラスローダに加えて、動的クラスローディングは他に二つのメカニズムを用います。その一つはクラスをワイヤ伝送するオブジェクト直列化システムであり、他方はローディングされたクラスをチェックするセキュリティマネージャです。 オブジェクト直列化に関する議論はしてはオブジェクト直列化仕様、セキュリティの問題に関しては セキュリティを参照してください。

クラスローダはどのようにして選択されるか

Java では、最初に Java クラスをロードするクラスローダがその後も使われてすべてのインタフェースと,そのクラスが直接使用するすべてのクラスをロードします。

パラメータまたは返り値として渡されるオブジェクト(上で説明した第二のケース)では、あるオブジェクトのクラスのためストリームにエンコードされた URL は次の手順で決定されます。

したがって、クラスが CLASSPATH からロードされたときには、codebase URL はそのクラスが RMI 呼び出しで使用されるときのストリーム上での注釈としてのみ使用されます。

アプリケーションは java.rmi.server.useCodebaseOnlyプロパティによって構成することができ、ネットワークホストからのクラスローディングを禁止して, ローカルに定義された codebase からのみロードさせることができます。 必要なクラスがロードできなければ、メソッド呼び出しは例外を発生して失敗します。

クライアントのブートストラッピング

RMI ランタイムがクライアントアプリケーションが必要とするすべてのクラスとインタフェースをロードできるためには、ブートストラッピングクライアントプログラムが必要であり、これがデフォルト以外のクラスローダ(例えば RMI クラスローダ)使用を強制します。 ブートストラッピングプログラムは次の条件を満たさなければなりません。

プログラム例:

import java.rmi.RMISecurityManager;
import java.rmi.server.RMIClassLoader;

public class LoadClient
{
	public static void main()
	{
		System.setSecurityManager(new RMISecurityManager());
		try {
			Class cl = RMIClassLoader.loadClass("myclient");
			Runnable client = (Runnable)cl.newInstance();
			client.run();
		} catch (Exception e) {
			System.out.println("Exception: " + e.getMessage());
			e.printStackTrace();
		}
	}
}
このコードがうまく動くためには、ブートストラッピングプログラムを実行するときに java.rmi.server.codebase プロパティを指定して、loadClass メソッドが URL によってクラスをロードするようにしなければなりません。 例えば:

java -Djava.rmi.server.codebase=http://host/rmiclasses/ LoadClient
プロパティを用いる代わりに、自分自身の URL を提供することも可能です。

Class cl = RMIClassLoader.loadClass(url, "myclient");
クライアントがスタートしてコントロールを持っていると、クライアントが必要とするすべてのクラスを特定の URL からロードさせることが可能です。このブートストラッピングテクニックは、アプレットが使用する同じクラスを AppletClassLoader を使って強制的にロードさせたのと全く同じ手法です。

このブートストラッピングテクニックを使わない場合は、クライアントのコードで直接参照されるクラスはクライアントの CLASSPATH の下になければなりません。しかも RMIClassLoader を使ってネットからダウンロードできる Java クラスはクライアントプログラムからは直接参照できないのです。これらのクラスにはスタブ、スケルトンそしてリモートメソッド呼び出しのパラメーター、返り値として使われる拡張クラスがあります。

セキュリティ

Java の場合は、クラスローダがローカル CLASSPATH からクラスをローディングすると、これらのクラスは信頼できるものとして扱われ、セキュリティマネージャからの制限を受けません。しかし、RMIClassLoader がネットワークからクラスをローディングするときは、セキュリティマネージャが存在しなければならず、もしない場合は例外がスローされます。

セキュリティマネージャは Java プログラムの最初のアクションとして起動され、それ以後の動作を管理できなければなりません。セキュリティマネージャはロードされたクラスが Java の標準的な安全規約に従っていることを保証します。クラスが信頼できるソースからロードされたか(例えばアプレットホスト)とか危険性のある機能にアクセスしなかったか等のチェックを行います。セキュリティマネージャが課す制限についての完全な解説は AppletSecurity クラスや RMISecurityManager RMISecurityManager クラスのドキュメントで読むことができます。

アプレットは常に AppletSecurity クラスの課す制限下にあります。セキュリティマネージャはクラスがアプレットホストかまたは信頼のおける codebase ホストのみからロードされるのを保証します。このため、アプレット開発者はアプレットホスト上に必要なクラスをインストールしなければなりません。

アプリケーションは自分のセキュリティマネージャを定義するか、または強い制限を課する RMISecurityManager を使うことになります。セキュリティマネージャが置かれていない場合は、アプリケーションはネットワークからクラスをロードすることができません。

クライアントやサーバプログラムは通常、ローカルシステムからロードされたクラスによって実装されますからセキュリティマネージャからの制限を受けません。しかし、クライアントプログラム自体がクライアントのブートストラッピングに解説されている方法でネットワークからダウンロードされた場合には、クライアントはセキュリティマネージャからの制限を受けることになります。

あるクラスが RMIClassLoader によってロードされると、そのクラスがそれ以後直接使用するクラスも RMIClassLoader によってロードされ、やはりセキュリティマネージャの管理を受けます。

セキュリティマネージャが置かれていても、java.rmi.server.useCodebaseOnly プロパティを true に設定するとクラスをストリームに埋め込んだ URL から直列化されたオブジェクトによってダウンロードすることが出来なくなります(この場合でもローカルに定義された java.rmi.server.codebase からロードすることは可能です)。 java.rmi.server.useCodebaseOnly プロパティはクライアントとサーバ両方で指定できますが、アプレットに対しては適用できません。

もし、アプリケーションが自分のセキュリティマネージャを定義し、それがクラスローダの作成を禁止した場合は、クラスはデフォルトの Class.forName メカニズムによってロードされます。 したがって、サーバは自身のポリシーをセキュリティマネージャとクラスローダを介して定義することができ、RMI システムはポリシーにしたがった動作をします。

セキュリティマネジャーはすべて java.lang.SecurityManager abstract クラスから拡張されますが、このクラスはリソースの消費に関しては制約を課しません。したがって、現在の RMISecurityManager はロードされたクラスがリソースを間違って使用することについての予防策を持っていません。新しいセキュリティメカニズムが開発されましたので、RMI はこれを使うことになるでしょう。

コンフィギュレーションシナリオ

RMI システムは多種類のシナリオをサポートしています。サーバはオープン、あるいはクローズ形式でコンフィギュレーションできます。アプレットはサーバ上でサポートされたオブジェクトのメソッドを呼び出すときに RMI を使うことができます。 アプレットがリモートオブジェクトを作成して、これをサーバに渡す場合に、サーバはそのリモートオブジェクトに呼び出しバックするときに RMI を利用することができます。 Java アプリケーションは RMI をクライアント/サーバモードか、ピア・トゥ・ピアのどちらかで使用することができます。この章ではこれらのコンフィギュレーション問題に焦点をあてます。

サーバ

典型的なクローズシステムシナリオでは、サーバはクラスをロードしないようにコンフィギュレーションされます。サーバが提供するサービスは、サーバマシンにローカルなリモートインタフェースによって定義されます。 サーバはセキュリティマネージャを持ちませんから、クライアントが URL を送ったとしてもサーバはクラスのローディングを行いません。 もし、サーバがスタブを持たないクラスのリモートオブジェクトを送ったとすると、メソッド呼び出しはそのリクエストが整列化される時点で失敗し、クライアントは例外を受け取ることになります。

よりオープンなサーバシステムでは、サーバがエクスポートするリモートオブジェクトのクラスがクライアントによりロードされ、クライアントが提供するリモートオブジェクトが必要とする場合だけにクラスをロードするように java.rmi.server.codebase を定義します。 サーバはセキュリティマネージャと RMI クラスローダの両方を持ち、これがサーバを保護します。さらに慎重にコンフィギュレーションしたい場合は、サーバは java.rmi.server.useCodebaseOnly プロパティを使って、クライアントが提供する URL からはクラスをロードできないようにします。

アプレット

典型的には、必要なクラスは、アプレットが現れる HTML ページに埋め込まれた URL が参照している HTTP サーバか FPT サーバが提供します。アプレットが利用する RMI ベースのサービスは、アプレットはそれがダウンロードされたホストへのネットワーク接続しかできませんから、アプレットをダウンロードしたサーバ上になければなりません。

例えば、通常のアプレットシナリオは HTML ページ、アプレットコード、RMI サービス、そしてブートストラップレジストリを提供する HTTP サーバのために単一のホストを使用します。 このシナリオでは、すべてのスタブ、スケルトン、そしてサポートクラスは HTTP サービスを使ってロードされます。 RMI サービスが提供してアプレットに渡される(そしてサーバに返されるかもしれない)すべてのリモートオブジェクトは RMI サービスがすでに知っているクラスのためのものです。 このケースでは、ネットワークからのクラスのローディングが起こりませんから RMI サービスの安全性は非常に高くなります。

アプリケーション

アプレットとは異なり、Java 言語で記述されるアプリケーションでは任意のホストへの接続が可能です。したがって、アプリケーションの場合にはクラスのソースと RMI サービスが実行されている場所のコンフィギュレーションについてより多くのオプションを持ちます。 典型的な例では、リモートクラスを提供するのは単一の HTTP サーバに限定し、RMI ベースのアプリケーションについてはネットワーク上のサーバとユーザのデスクトップに分散させます。

アプリケーションがローカルにロードされるときは、そのプログラムが直接使用するクラスもローカルに利用可能でなければなりません。 このシナリオではネットワーク上のソースからダウンロードされるのは、リモートインタフェースのクラス、スタブクラス、そしてリモートメソッド呼び出しで渡されるまたは返り値となる拡張クラスだけです。

アプリケーションがローカルディレクトリからロードされずに、クライアントのブートストラッピングで説明されるメカニズムを使ってネットワークソースからロードされる場合には、アプリケーションが使用するすべてのクラスはやはり同じネットワークソースからダウンロードすることができます。

ネットワークソースからのダウンロードを可能にするためには、各リモートオブジェクトサーバは、アプリケーションクラスと生成されたスタブ/スケルトンの所在を指定する java.rmi.server.codebaseプロパティを使ってコンフィギュレーションされなければなりません。 codebase プロパティが指定されると、RMI システムはクラスの URL を直列化されたクラスの形式で埋め込みます。

たとえ直列化されたオブジェクトのクラスがクラスをダウンロードできる URL で指定されたとしても、クラスやピアはクラスがローカルに利用可能である限りローカルにロードしようとします。

プロキシ経由で RMI をファイアウオールを通して使う

RMI のトランスポート層は通常 Internet 上のホストへ直接ソケットを開こうとします。 しかし、多くの Intranet はファイアウオールを備えているためこれができません。 このため、デフォルト RMI トランスポートはこれにかわる2種類の HTTP ベースのメカニズムを備えて、ファイアウオールの後ろにいるクライアントがファイアウオールの彼方にあるリモートオブジェクト上のメソッドを呼び出せるようにしています。

RMI 呼び出しは HTTP プロトコルの中でどのようにパッケージされるか

ファイアウオールの彼方に到達できるように、トランスポート層は firewall-trusted HTTP プロトコルに RMI 呼び出しを埋め込んでおきます。 RMI 呼び出しのデータは HTTP POST リクエストの本体として外へ送り出され、返される情報も HTTP による応答本体の一部として組み込まれています。トランスポート層は POST リクエストを次の2つのいずれかの方法で形式を整えます。

  1. ホストマシンの任意のポートに向けられた HTTP リクエストをファイアウオールプロキシが転送する場合に、そのリクエストは RMI サーバが受信しているポートへ直接転送されます。 サーバマシン上のデフォルトの RMI トランスポート層は、POST リクエストの中の RMI 呼び出しを理解してデコードできるサーバソケットを使って受信しています。
  2. ファイアウオールプロキシが HTTP リクエストを良く知られた HTTP ポートにのみ転送する場合には、そのリクエストはホストマシン上のポート番号 80 で受信しているサーバへ転送され、CGI スクリプトが実行されてその呼び出しを同じマシン上のターゲット RMI サーバのポートへ転送します。

デフォルトソケットファクトリ

RMI のトランスポートは java.rmi.server.RMISocketFactory クラスを拡張して、クライアントとサーバソケットへのリソースプロバイダとなるソケットファクトリのデフォルト実装を提供しようとします。 このデフォルトソケットファクトリは、次に説明する方法でファイアウオールを透明に通り抜けるメカニズムを備えたソケットを作り出します。

このようなデフォルト動作をするクライアント側ソケットはファクトリの java.rmi.server.RMISocketFactory.createSocket メソッドが提供します。 このようなデフォルト動作をするサーバ側のソケットはファクトリの java.rmi.server.RMISocketFactory.createServerSocket メソッドが提供します。

クライアントのコンフィギュレーション

クライアント側ではファイアウオールを通り抜けて RMI 呼び出しを送るための特別なコンフィギュレーションは必要ありません。

しかし、クライアントは java.rmi.server.disableHttp プロパティのブール値を true に設定して RMI 呼び出しを HTTP リクエストの形式にパッケージするのを禁止させることができます。

サーバのコンフィギュレーション

ホスト名はホストの IP アドレスとして指定されてはなりません。ファイアウオールプロキシの中にはそのような形式のホスト名を転送しないものがあるからです。

  1. サーバホストのドメインの外にあるクライアントがあるサーバのリモートオブジェクトを呼び出せるためには、クライアントはまずそのサーバを見つけ出せなければなりません。このためには、サーバがエクスポートするリモート参照がそのサーバの完全修飾名を含んでいなければなりません。 サーバのプラットフォームとネットワーク環境によっては、サーバが実行中の Java 仮想マシンがこのような情報を利用できない場合があります。利用できないときは、ホストの完全修飾された名前はサーバがスタートする時点で java.rmi.server.hostname プロパティとして指定されていなければなりません。

    例えば、次のコマンドでマシン chatsubo.javasoft.com 上の RMI サーバクラス ServerImpl をスタートさせることができます。

       java -Djava.rmi.server.hostname=chatsubo.javasoft.com ServerImpl
    
  2. もしサーバが、ファイアウオールの彼方にある、任意のポートへ転送できる RMI クライアントをサポートしないならば、次のコンフィギュレーションを使うことができます。
    1. HTTP サーバはポート番号 80 を受信用に使用する。
    2. CGI スクリプトをエイリアスURLパス /cgi-bin/java-rmi に置きます。このスクリプトは、

機能上の問題と制限

HTTP リクエストを介して送信された呼び出しは、プロキシによる転送の時間遅れを除いたとしても、直接ソケットを介した場合よりもはるかに遅くなります。

ファイアウオールを通す場合、HTTP リクエストは一方向でのみ開始できるため、クライアントは自分のリモートオブジェクトをファイアウオールの外へエクスポートすることはできません。これはファイアウオールの外にあるホストが内側にあるクライアントのメソッド呼び出しを開始できないためです。



目次 前項目 次項目

Copyright (C) 1996, 1997 Sun Microsystems, Inc. All rights reserved.