こんにちはRMIアプリケーションがあり、クライアントからサーバーでいくつかのメソッドを呼び出そうとしています。私は次のコードを持っています:
_public static void main(final String[] args) {
try {
//Setting the security manager
System.setSecurityManager(new RMISecurityManager());
IndicatorsService server = (IndicatorsService) Naming
.lookup("rmi://localhost/" + IndicatorsService.SERVICE_NAME);
DataProvider provider = new OHLCProvider(server);
server.registerOHLCProvider(provider);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
_
サーバーは正しくロードされていますが、server.registerOHLCProvider(provider);
を呼び出そうとすると、次のエラーが表示されます。
_ Java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
Java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
Java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
at Sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.Java:336)
at Sun.rmi.transport.Transport$1.run(Transport.Java:159)
at Java.security.AccessController.doPrivileged(Native Method)
at Sun.rmi.transport.Transport.serviceCall(Transport.Java:155)
at Sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.Java:535)
at Sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.Java:790)
at Sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.Java:649)
at Java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.Java:886)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:908)
at Java.lang.Thread.run(Thread.Java:662)
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 sk.fri.statistics.service.impl.IndicatorsServiceImpl_Stub.registerOHLCProvider(Unknown Source)
at sk.fri.statistics.service.Client.main(Client.Java:61)
Caused by: Java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
Java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
at Sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.Java:296)
at Sun.rmi.transport.Transport$1.run(Transport.Java:159)
at Java.security.AccessController.doPrivileged(Native Method)
at Sun.rmi.transport.Transport.serviceCall(Transport.Java:155)
at Sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.Java:535)
at Sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.Java:790)
at Sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.Java:649)
at Java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.Java:886)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:908)
at Java.lang.Thread.run(Thread.Java:662)
Caused by: Java.lang.ClassNotFoundException: sk.xorty.client.providers.OHLCProvider (no security manager: RMI class loader disabled)
at Sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.Java:375)
at Sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.Java:165)
at Java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.Java:620)
at Java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.Java:247)
at Sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.Java:197)
at Java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.Java:1574)
at Java.io.ObjectInputStream.readClassDesc(ObjectInputStream.Java:1495)
at Java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.Java:1731)
at Java.io.ObjectInputStream.readObject0(ObjectInputStream.Java:1328)
at Java.io.ObjectInputStream.readObject(ObjectInputStream.Java:350)
at Sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.Java:306)
at Sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.Java:290)
... 9 more
_
ポリシーファイルをVM引数として追加しました。次のようになります。
_grant {
permission Java.security.AllPermission;
}
_
無効なクラスローディングについて何か言い続けているので、問題はどこかにあると思います...ありがとう!
リモートクラスのロードには注意が必要です。
元の投稿には、コードベースに関する情報は含まれていません。クライアントのセキュリティ構成は正しいが、リモートコードにアクセスできない可能性があります。クラスは、クライアントによって「コードベース」から直接ロードされます。 RMI接続を介したサービスによってクライアントに提示されることはありません。サービスは単にクラスの外部ソースを参照します。
サーバーは、システムプロパティJava.rmi.server.codebase
を指定する必要があります。値はURLである必要がありますクライアントがアクセス可能そこから必要なクラスをロードできます。これがfile:
URLの場合、ファイルシステムクライアントからアクセス可能である必要があります。
他の方法:サーバーがクライアントからクラスをロードできるようにする必要がある場合(次のように)、クライアントはコードベースプロパティをサーバーからアクセス可能なURLに設定する必要があります。
RMI動的プロキシでメソッドを呼び出すたびに、 MarshalInputStream
(これは ObjectInputStream
を拡張してresolveClass
をオーバーライドしますおよびresolveProxyClass
)が LoaderHandler
に委任して、使用するClassLoader
の3つの場所を検索します。
latestUserDefinedLoader()
と呼ばれるハックを使用します。JREの一部ではないスタックの最初のメソッドを探してスタックを調べます)。contextClassLoader
Java.rmi.server.useCodebaseOnly=false
_の場合、コードベースClassLoaderはremote_Java.rmi.server.codebase
_のURLを使用します。 seCodebaseOnlyのデフォルト値はJDK 7u21で変更されたため、変更しない限りリモートコードベースは使用されません !Java.rmi.server.codebase
_のURLを使用します。そのため、Remoteメソッドを呼び出すときにClassNotFoundException
を取得する理由はいくつか考えられます。
-Djava.rmi.server.useCodebaseOnly=true
_を以前の動作に一致するように設定するか、_-Djava.rmi.server.codebase
_を両方のローカルでURLのスペース区切りリストに設定しますそして遠隔側。そして、コンピューターがそれらのURLにアクセスできることを確認してください。Thread.setContextClassLoader(ClassLoader)
を呼び出してください。 (これが私の問題でした:EventDispatchThreadでcontextClassLoaderが設定される前に作成されたワーカースレッドにたまたまスケジュールされたSwingWorker
がありました)。たとえば、AとCはカスタムClassLoaderに属しますが、Bは親ClassLoaderに属します。a.getB()。getC()を呼び出すと、getB()呼び出しはカスタムクラスローダーを使用しますが、getC()呼び出しはlatestUserDefinedClassLoaderでCを見つけられず、contextClassLoaderにフォールバックする必要があります。これらはすべて、ObjectInputStreamの貧弱なAPI設計に関する警告物語です。 ObjectInputStreamでは、latestUserDefinedLoader、contextClassLoader、およびcodebaseを使用して偶然にパラメータを見つけようとするのではなく、ClassLoaderパラメータを渡す必要があります。
クライアント側だけでなく、サーバー側でもsecurity managerが必要です。
これがないと、サーバーのRMIエンジンはクライアントからのクラスのロードを拒否します。これは、これらがサーバー上で悪事を起こさないことを保証できないためです。
RMIクラスの読み込みが必要ですか?サーバーは、クライアントが送信しようとするクラスをすでに持っていませんか?