1

localhost で実行しているときに RMI レジストリに正しくバインドする RMI サーバーがあります (正しくセットアップされていることを示すため)。これを行うコードは次のとおりです。

 private void exposeTickHistoryRemoteProvider(TickHistoryRemoteInterface aTickHistoryServer) {
        if (System.getSecurityManager() == null) {
            SecurityManager mySecurityManager = getSecurityManager();
   System.setSecurityManager(mySecurityManager);
        }
  String rmiServerHostname = System.getProperties().getProperty("java.rmi.server.hostname");
  try {
   TickHistoryRemoteInterface stub =
                (TickHistoryRemoteInterface) UnicastRemoteObject.exportObject(aTickHistoryServer, 0);
            Registry registry = LocateRegistry.getRegistry(rmiServerHostname);
            String[] services = registry.list();
            registry.rebind(RMI_SERVICENAME_REUTERS_TICKHISTORY_SERVER, stub);
            log.info(RMI_SERVICENAME_REUTERS_TICKHISTORY_SERVER + " bound");
        } catch (Exception e) {
         log.error(RMI_SERVICENAME_REUTERS_TICKHISTORY_SERVER + " exception:" + e.toString());
            e.printStackTrace();
        }
    }

私のローカルホストは、次のバージョンの Java で Windows を実行しています。

C:\eclipse>java -version
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode)

ここで、私の問題は、別のマシン (OpenJDK IcedTea6 1.8.1、Java バージョン 1.6.0_18 を使用して Ubuntu 10.04 を実行) で実行されている RMIRegistry にバインドしたいということです。

この Ubuntu マシンでは、CLASSPATH に何もなく (echo $CLASSPATH)、OpenJDK RMIRegistry を実行しています (Ubuntu にバンドルされているものとは対照的に):

sudo /usr/lib/jvm/java-6-openjdk/jre/bin/rmiregistry &

上記のコードで、変数 rmiServerHostname が "localhost" で、RMIRegistry が Windows localhost で実行されている場合、コードは正しく機能します (RMI サーバー コードは RMI レジストリにバインドされます)。ただし、rmiServerHostname がリモート Ubuntu マシン (「deity」) の場合、「rebind」呼び出しで次の例外がスローされます。

 java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
 java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
 java.lang.ClassNotFoundException: com.relative.tickhistory.provider.TickHistoryRemoteInterface
 java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
 java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
 java.lang.ClassNotFoundException: com.relative.tickhistory.provider.TickHistoryRemoteInterface

RMIRegistry を強制終了すると、別のエラー メッセージが表示されます (当然のことですが)。

 java.rmi.ConnectException: Connection refused to host: deity; nested exception is: 
 java.net.ConnectException: Connection refused: connect
 at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source)
 at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source)
 at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source)
 at sun.rmi.server.UnicastRef.newCall(Unknown Source)
 at sun.rmi.registry.RegistryImpl_Stub.list(Unknown Source)

これらの RMIRegistry の実装 (Windows Java6 と Ubuntu OpenJDK 6) の間に非互換性はないと思いますが、この問題を解決する方法がわかりません。特に、コードが正しく機能することを知っているためです (最初の Windows/localhost の例)。


これまでの進捗

役立つ回答をありがとうございます。rmiServerHostname (ローカルホストで実行) と rmiRegistryHostname ('deity' で実行) の間で混乱していたことは理解しています。次のようにコードを修正しましたが、まだ同じ問題が発生しています (「Registry registry = LocateRegistry.getRegistry( rmiRegistryHostname )」という行の変更に注意してください)。

    String rmiServerCodebase = System.getProperties().getProperty("java.rmi.server.codebase");
    String rmiServerHostname = System.getProperties().getProperty("java.rmi.server.hostname");
    String rmiRegistryHostname = "deity";
    System.out.println("rmiServerCodebase=" + rmiServerCodebase + "; rmiServerHostname=" + rmiServerHostname);
    try {
        TickHistoryRemoteInterface stub =
            (TickHistoryRemoteInterface) UnicastRemoteObject.exportObject(aTickHistoryServer, 0);
        Registry registry = LocateRegistry.getRegistry(rmiRegistryHostname);

printステートメントの出力は次のとおりです(注、私のローカルホストは「RTPC-16」です)

"rmiServerCodebase=file:///C:/workspace/DEV/ReutersTickHistoryServer/ReutersTickHistoryInterface.jar; rmiServerHostname=RTPC-16"

このファイルは存在します:

C:\>dir c:\workspace\DEV\ReutersTickHistoryServer\ReutersTickHistoryInterface.jar
 Volume in drive C is OS
 Volume Serial Number is 7AEB-A105

 Directory of c:\workspace\DEV\ReutersTickHistoryServer

22/10/2010  12:21 PM             9,467 ReutersTickHistoryInterface.jar
               1 File(s)          9,467 bytes

したがって、もう一度要約すると、次のようになります。

  • このコードは、RMIRegistry と RMIServer が同じ物理ホスト (例: localhost) にある場合に機能します。
  • この問題は、別のホストで RMIRegistry プロセスのみを実行しようとしたときに発生します (つまり、RMIServer がローカルホストの「RTPC-16」で実行されているときに、RMIRegistry が「deity」で実行されている場合)。
  • クライアントとサーバーの両方に RMI インターフェイス コードベース ("ReutersTickHistoryInterface.jar") をバンドルしていたので、RMI がクラス定義を転送する必要があるとは予想していませんでした。RMI はクライアント上でスタブ クラスを作成し、実際の RMI 呼び出しを処理するだけです。
4

2 に答える 2

0

また、java.rmi.server.hostname を誤用しています。それはそのためではありません。このコードはレジストリにバインドされており、レジストリが同じホストで実行されている場合にのみ実行できるため、バインドまたはバインド解除のためにレジストリ参照を取得するときは「localhost」を使用する必要があります。

于 2010-10-27T08:05:22.393 に答える
-1

この例外が発生するのは、rmiregistry がリモート オブジェクトのスタブまたはスタブに必要な他のクラスを見つけられないためです。java.rmi.server.codebaseサーバーの起動時にプロパティを指定し、実装スタブの場所に設定する必要があります。これは、スタブ クラスをレジストリに動的にダウンロードできるようにするために必要です。

このプロパティの詳細については、 RMIチュートリアルを使用した動的コードのダウンロードを参照してください。

于 2010-10-27T07:36:51.060 に答える