Привет, у меня есть приложение 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
Я добавил свой файл политики в качестве аргумента виртуальной машины , вот как это выглядит:
grant {
permission java.security.AllPermission;
}
Он постоянно что-то говорит об отключенной загрузке классов, так что, думаю, проблема где-то там ... Спасибо!
Я знаю, почему это происходит. например, вы запускаете сервер в проекте A, но вы используете клиент в проекте B для запроса этого сервера, это неправильно. Поэтому вы должны поместить сервер и клиента в один и тот же проект.
Вам нужен менеджер безопасности на стороне сервера, а не только на стороне клиента.
Без этого механизм RMI сервера отказывается загружать классы с клиента, поскольку он не может гарантировать, что они не будут делать зла на сервере.
Вам нужна загрузка класса RMI? Может ли сервер уже иметь классы, которые клиент пытается отправить?
Каждый раз, когда вы вызываете метод для динамического прокси RMI, MarshalInputStream
(который расширяет ObjectInputStream
для переопределения resolveClass
и resolveProxyClass
) делегатов LoaderHandler
искать в 3 местах для использования ClassLoader
:
latestUserDefinedLoader()
: он идет вверх по стеку, ища первый метод в стеке, который не является частью JRE). contextClassLoader
вызывающего абонента java.rmi.server.useCodebaseOnly=false
, то кодовая база ClassLoader использует URL-адреса в remote java.rmi.server.codebase
. Обратите внимание, что значение по умолчанию useCodebaseOnly изменилось в JDK 7u21 , так что удаленная кодовая база больше не используется, если вы не измените ее ! java.rmi.server.codebase
. Итак, есть несколько возможных причин, по которым вы получите ClassNotFoundException
при вызове метода Remote:
-Djava.rmi.server.useCodebaseOnly=true
в соответствии с предыдущим поведением, либо установите -Djava.rmi.server.codebase
в список разделенных пробелами списков URL как на локальном, так и на локальном отдаленные стороны. И убедитесь, что компьютер может получить доступ к этим URL. Thread.setContextClassLoader(ClassLoader)
, чтобы RMI использовал этот ClassLoader. (Это была моя проблема: у меня было SwingWorker
, которое было запланировано на рабочий поток, который был создан до того, как contextClassLoader был установлен на EventDispatchThread). Например, A и C принадлежат вашему пользовательскому ClassLoader, но B принадлежит родительскому ClassLoader, тогда когда вы вызываете a.getB (). GetC (), вызов getB () будет использовать пользовательский загрузчик классов, но вызов getC () не сможет найти C в latestUserDefinedClassLoader и должен будет вернуться к contextClassLoader. Все это предостерегающая история о плохом дизайне API ObjectInputStream. ObjectInputStream должен был требовать, чтобы вы передавали параметр ClassLoader, а не пытались найти его случайно, используя lastUserDefinedLoader, contextClassLoader и codebase.