2003年度 データベース論

RMI
ソフトウェア特論
第6回 / 2004-06-04
お知らせ

6月11日 (金) の講義は休講となります。
きょうの目標

RMI の基本を復習する。
RMI とは何か
RMI とは




Remote Method Invocation (遠隔メソッド
呼び出し) の略
違う Java Virtual Machine 上のメソッドを
呼び出す仕組みのこと
Java Virtula Machine は、別のホスト上に
あってもよい。
クライアント・サーバモデルとなる。
通常のJavaプログラムの場合


Hello クラスのインスタンスを作成する。
このインスタンスの sayHello メソッドを実
行する。
RMIの場合
RMI の場合




クライアントで Hello クラスのインスタンス
を作成する。
クライアントで、このインスタンスの
sayHello メソッドを実行する。
Hello クラスの実装はサーバ側にある。
サーバで sayHello メソッドが実行され、返
値がクライアントに返される。
RMI だと何がうれしいのか


Hello クラスの実装はサーバ側にあるので、
クライアントはサーバ側を呼び出すだけで
よい。
このときクライアントは、メソッドを実行する
だけでサーバを呼び出せる。
RMIのしくみ
サーバとクライアント


サーバでは、クライ
アントから呼び出さ
れるメソッドを実装
する。
クライアントでは、
サーバを見つけだ
して、メソッドを実行
する。
スタブとスケルトン


RMI では、通信に
必要な処理は「スタ
ブ」と「スケルトン」
というクラスに記述
される。
スタブとスケルトン
は、サーバのプロ
グラムからツール
で生成される。
rmiregistry


サーバの情報を登
録しておくための
「ネームサーバ」
クライアントは
rmiregistry にアク
セスしてサーバの
プログラムを探す
RPC (Remote Procedure Call)




RMI の原型となった技術
Sun Microsystems によって開発された。
別のマシン上にある手続きを実行するた
めのしくみ。
Unix, Windows で広く普及している。
RMI を構成するプログラム
Remoteインタフェース (1)
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
public String sayHello()
throws RemoteException;
}
Remoteインタフェース (2)





クライアントから呼び出せるメソッドを定義
する。
サーバは、このインタフェースを実装する。
このインタフェースをサーバとクライアント
で共有する。
java.rmi.Remote を継承する。
それぞれのメソッドは、RemoteException
を発行できるようにする。
サーバ側のプログラム (1)
クラスの定義
public class HelloImpl
extends UnicastRemoteObject
implements Hello {
......
}
サーバ側のプログラム (2)
クラスの定義


Hello インタフェースを実装する。
UnicastRemoteObject を継承する。
サーバ側のプログラム (3)
コンストラクタとメソッド
public HelloImpl() throws RemoteException {
super();
}
public String sayHello()
throws RemoteException {
return "Hello world!";
}
サーバ側のプログラム (4)
コンストラクタとメソッド



RemoteException を発行するようにする。
そのため、必ずコンストラクタを用意しなけ
ればならない。
インタフェースで用意されたメソッドを実装
する。
サーバ側のプログラム (5)
mainメソッド (1)
// 許可されてない操作を行わないために
if (System.getSecurityManager() == null)
{
System.setSecurityManager(
new RMISecurityManager()
);
}
サーバ側のプログラム (6)
mainメソッド (2)
// インスタンスを生成
HelloImpl obj = new HelloImpl();
// rmi://localhost/HelloServer といった
// URIを生成する
StringBuffer url = new StringBuffer();
url.append("rmi://");
url.append(args[0]);
url.append("/HelloServer");
サーバ側のプログラム (7)
mainメソッド (3)
// rmiregistry に
// HelloImpl を
// rmi://localhost/HelloServer という名前で
// 登録する
Naming.rebind(new String(url), obj);
クライアント側のプログラム (1)
// rmi://localhost/HelloServer といった
// URIを生成する
StringBuffer url = new StringBuffer();
url.append("rmi://");
url.append(args[0]);
url.append("/HelloServer");
クライアント側のプログラム (2)
// rmiregistry から
// rmi://localhost/HelloServer という名前の
// オブジェクトを探し、Hello にキャストする
Hello obj = (Hello)Naming.lookup(
new String(url));
クライアント側のプログラム (3)
// Hello オブジェクトの
// sayHello メソッドを実行する
System.out.println(obj.sayHello());
RMI を動かす
プログラムのコンパイル



javac Hello.java
javac HelloImpl.java
javac HelloClient.java
スタブとスケルトンの生成


rmic HelloImpl
このコマンドによって、次の2つのクラスが
生成される。



HelloImpl_Stub.class
HelloImpl_Skel.class
rmic –keep HelloImpl を実行することで、
スタブとスケルトンのソースファイルを残す
ことができる。
サーバ側とクライアント側で
用意するプログラム

サーバ側





Hello.class
HelloImpl.class
スタブ
スケルトン
policy.txt (後述)

クライアント側



Hello.class
HelloClient.class
policy.txt (後述)
rmiregistry の起動



start rmiregistry
このコマンドで rmiregistry を起動
起動するフォルダにはクラスファイルを置
かない
サーバの起動 (1)
コマンドライン
java -Djava.rmi.server.codebase=
file:///C:\Home\rmi\
-Djava.security.policy=policy.txt
HelloImpl localhost
サーバの起動 (2)
codebase (1)
java.rmi.server.codebase=
file:///C:\Home\rmi\


codebase プロパティでスタブの位置を指
定する。
この場合は、C:\Home\rmi\ にスタブを置
いておく。
サーバの起動 (3)
codebase (2)

C:\Home\rmi\


最後の \ を忘れない
Codebase には Web上の URL を指定す
ることもできる。


http://www.wakhok.ac.jp/~tomoharu/
この URL にスタブを置いておく
サーバの起動 (4)
codebase (3)

クライアントが起動されると、codebase で
指定された URL からスタブがダウンロード
されて、クライアントプログラムからスタブ
を利用できるようになる。
サーバの起動 (5)
ポリシーファイルの設定
java.security.policy=policy.txt

policy.txt というファイルでアクセス権を指
定できる。
サーバの起動 (6)
policy.txt の内容
grant {
// Allow everything for now
permission java.security.AllPermission;
};

すべての人にすべてのアクセス権を与える
クライアントの起動

java -Djava.security.policy=policy.txt
HelloClient localhost
注意点



Cygwin を使うとうまく動かない (原因は不
明)。
プログラムを起動するときには、クラスパス
を設定しないこと。
クラスパスを設定していると、もしクラスパ
ス中にスタブがあった場合、クライアントプ
ログラムはそのスタブをロードするから。
参考文献・URL

JavaTM Remote Method Invocation
(RMI)


http://java.sun.com/j2se/1.4/ja/docs/ja/gui
de/rmi/
Sun Microsystems による RMI の解説です。