RMIでリモートコールしてくれない件

以下のようなクラスがあって、

Echo.java

package rmitest;

import java.io.Serializable;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Echo extends Remote, Serializable{

    public String sayEcho(String message) throws RemoteException;
    
}


EchoImpl.java

package rmitest;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class EchoImpl implements Echo{

    public String sayEcho(String message)  {
        System.out.println("server=" + message);
        return message;
    }
    
    public static void main(String[] args) throws Exception{
        
        Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
    
        Echo echo = new EchoImpl();
        //Remote remote= UnicastRemoteObject.exportObject(echo, 0);
        //registry.rebind("echo", remote);
        registry.rebind("echo", echo);     

        System.out.println("wait");
        synchronized(EchoImpl.class){
            EchoImpl.class.wait();
        }
        System.out.println("end");
    }
}


EchoClient.java

package rmitest;

import java.rmi.Naming;

public class EchoClient {

    public static void main(String[] args) throws Exception {
        Echo echo = (Echo)Naming.lookup("echo");
        String message = echo.sayEcho("hoge");
        System.out.println("client=" + message);
    }
    
}


EchoImplを実行、EchoClientを実行すると、期待している動作では、


サーバーのコンソール

server=hoge


クライアントのコンソール

client=hoge


となるはずであるが、
実際は、以下のようになる。


クライアントのコンソール

server=hoge
client=hoge


exportObject(あるいはUnicastRemoteObjectを継承)せずに、レジストリにバインドすると、リモート呼び出しにならずに、ローカル呼び出し(newして実行?)になるらしい。RMIってそういう挙動だったのか。今日はじめて知りました。これで朝1時間ははまった。

スタブ不要なRMI

http://www.02.246.ne.jp/~torutk/javahow2/rmi_nostub.html


オプション指定でちょっとはまった。レジストリ側で、セキュリティポリシーとクラスパス(コードベース)の指定が必要みたい。
rmiregistryコマンドで起動する場合は、オプションを指定する。
Javaプログラム内でLocateRegistry#createRegistryで作る場合は、Javaプログラムの起動パラメータで必要に応じて指定(同じプロセスでレジストリ作ってバインドとかなら、セキュリティやコードベースの指定も不要かも)。


あと、UnicastRemoteObjectをextendsしてないと、リモートコールしてくれないのにはまった。
UnicastRemoteObject#exportObject(Remote)つかえないみたいだから、継承しないといかんのかなー