1

環境

これは Java RMI を使用するアプリケーションで、次のものがあります。

  • ホスト A 上のクライアントとホスト B 上のサーバー。
  • ホスト A 上の HTTP サーバー。クライアントとサーバーが使用するすべてのクラスのコピーを保持します。
  • RMI レジストリはサーバー コードから作成され、サーバー JVM と CLASSPATH を共有します。

サーバーおよびクライアント アプリケーションの場合:

  • java.rmi.server.codebaseプロパティは (コード内で) HTTP サーバーの URL に設定されます。
  • 適切なポリシーを備えたセキュリティ マネージャーが配置されています。
  • java.rmi.server.hostnameLAN アドレスに設定されます。

メソッド呼び出し:

  • サーバー メソッドは、型WorkRequest(抽象クラス) のパラメーターで定義されます。
  • クライアントは、サブクラスを使用してこのメ​​ソッドを呼び出しますWorkRequestSquare
  • WorkRequestSquareサーバーコードでは決して言及されていません

サーバーコード

Object execute(WorkRequest work) throws RemoteException { return work.execute(); }

クライアントコード:

try { servant.execute(new WorkRequestSquare(123)); }
catch (RemoteException e) {
    System.out.println("Error while submitting work request:");
    e.printStackTrace();
}

このコードは、サーバーの CLASSPATH にすべての関連クラスがあり、動的ロードが必要ない場合に機能します。

問題

サーバー側で CLASSPATH から削除WorkRequestSquareすると、クライアント側で例外がスローされます (サーバー側では何もスローされません)。

Error while submitting work request:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: WorkRequestSquare
    at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
    ...

WorkRequestSquareサーバーコードで明示的に言及されていないため、動的にロードできるはずですが、そうはなりません。

バイパス

Stuart Marks から、プロパティjava.rmi.server.useCodebaseOnlyを に設定する必要があることがわかりましたfalse

このプロパティのデフォルト値は、JDK 7u21 でfalseからに変更されました。を使用してローカルに定義された場所を除いて、JVM が任意の場所からクラスを動的にロードするのを防ぐために設定します。これは、パラメーターをマーシャリングするときにクライアント JVM によって設定されたコードベース値が、サーバーによって無視されることを意味します。true useCodebaseOnlytruejava.rmi.server.codebaseWorkRequestSquareuseCodebaseOnlytrue

サーバーで がにuseCodebaseOnly設定さfalseれ、WorkRequestSquareクラスがサーバーの CLASSPATH から削除されると、サーバーは HTTP サーバーからクラス定義を取得するようになりました。これは有効なバイパスです。

質問

クライアントとサーバーのプロパティの値が同じであるため、まだ何か異常がありcodebaseます。

useCodebaseOnlyサーバーにデフォルト設定された場合true、JVM は RMI ストリームに追加されたクライアントを無視する必要がありましたが、クラスを取得するためにcodebase独自のものを使用する必要がありました。codebaseWorkRequestSquare

codebaseクライアントとサーバーの値が同じであるため、これはとにかく成功するはずです。

誰かがその問題に光を当てることができますか?

4

1 に答える 1

0

クラスパスに含める必要があるクラスの最小セットは何ですか?

クライアント コードで実際に名前で使用されるクラス。たとえば、リモート インターフェイス、仮引数の型と結果、リモート メソッド シグネチャで名前が付けられた例外の型などです。

/ コードベースサーバーを使用して利用できる場合、クラスパスで欠落している可能性のあるクラスは何ですか?

上記のクラスまたはインターフェイスを実装し、クライアント コードで名前によって使用されないクラス。

RMI 通信 (Eclipse プラグインなど) をデバッグし、ネットワーク スニファの使用を回避するツールはありますか?

確かに Eclipse プラグインがありました。何年も前に見ましたが、実際に必要になったことはありません。

于 2014-08-14T23:11:23.517 に答える