サーバーがクライアント側の定義されたクラスを必要としない単純な状況で正常に動作する 2 台のマシンに RMI クライアント/サーバーをセットアップしています。ただし、クライアント側で定義されたクラスを使用する必要がある場合、サーバーにそれらのクラスを非整列化させることができません。java.rmi.server.codebase
これは、クライアント アプリへの引数として渡すプロパティに問題があると思われます。私は Sun の RMI チュートリアル トレイルに従いましたが、ルート パッケージ ディレクトリのすぐ上のディレクトリで実行されるため、クライアントとサーバーを実行するときにクラスパス引数を指定しないことを除いて、手順に正確に従っていると思います (ただし、これも試してみました)。効果)。
以下で詳しく説明するさまざまなクライアント側の組み合わせを実行しようとしたときに発生する例外はすべて同じです。
RmiServer exception:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: test.MyTask
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:353)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
at $Proxy0.execute(Unknown Source)
at test.myClient.main(myClient.java:32)
詳細は次のとおりです。
私のクライアント/サーバー rmi は、ルーターの背後にあるホーム ネットワーク上にセットアップされています。ルーターは、私が呼び出す静的 IP アドレスに割り当てられていますmyhostname
。適切なマシンを指す適切なポート マッピングがルーターに設定されます。
役割、マシン、OS、IP アドレス:
server, venice, linux ubuntu 9.10, 10.0.1.2
client, naples, mac os x leopard, 10.0.1.4
内部で次のようにサーバー側を起動します/home/andrews/workspace/epsilon/bin
。
1 デフォルト ポート 1099 でレジストリを開始します。
venice% rmiregistry &
2 共通インターフェイスのコード ベースを指すポート 2001 で Web サーバーを起動します。
venice% java webserver/ClassFileServer 2001 /home/andrew/workspace/epsilon/bin
3 サーバー オブジェクトを登録するサーバー アプリ (test/myServer のメイン クラス) を起動します。
venice% java -Djava.rmi.server.codebase="http://myhostname:2001/" -Djava.security.policy=server.policy -Djava.rmi.server.hostname=myhostname test/myServer &
内部のクライアント側/Users/andrews/Development/Java/workspace/epsilon/bin
:
1 クライアント側のクラスをサーバーに提供できるローカル Web サーバーを開始します (これが必要かどうかはわかりませんが、試してみましたが、まだ成功していません。2001 から のルーターにポートマッピングを追加しましたvenice
。 2002年~naples
)
naples$ java webserver/ClassFileServer 2002 /Users/andrews/Development/Java/workspace/epsilon/bin/
-cp
クライアントを実行しようとしています (注:クライアントはルート パッケージ ディレクトリのすぐ上で実行されるため、引数は指定しません):
1 http ホスト名を使用して #1 を試す
naples$ java -Djava.rmi.server.codebase=http://10.0.1.4:2002/ -Djava.security.policy=client.policy test.myClient myhostname
注 1:myhostname
最後の引数はクライアントに渡され、サーバーの rmi ホスト名に解決されます。
注 2:localhost:2002
代わりに10.0.1.4:2002
too を使用してみました。
注 3:がルーターに割り当てられており、適切なポート マッピングが設定されているため、使用してみました。このアドレスは解決される必要がmyhostname:2002
あります。myhostname
naples
venice
2 #2 を試す:
naples$ java -Djava.rmi.server.codebase=file:/Users/andrews/Development/Java/workspace/epsilon/bin/ -Djava.security.policy=client.policy test.myClient myhostname
注 1: コード ベースの URL 形式は正しいです。現在のファイル ディレクトリ パスを URL に変換する小さなプログラムを作成し、それを使用しました。を使用しfile:///Users...
ても同じ効果があります。
その他の注意事項:
1 サーバーとクライアントのポリシー ファイルでパスが正しく指定されています。これは、このセットアップを良いパスと悪いパスでテストし、悪いパスのセキュリティ例外を取得したためです。
2 このセットアップは、クライアント側で定義されたオブジェクトを使用しない場合に機能し、クライアントはサーバーに正しく接続され、サーバーが実行されます。
3 サーバー上のクライアント側クラスをサーバーのクラスパスに配置すると、すべて正常に実行されます。
すべての助けに感謝します。