Java: нет менеджера безопасности: загрузчик классов RMI отключен [дубликат]

этот вопрос уже есть ответ здесь:

Привет у меня есть приложение 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.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.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.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;
}

он продолжает говорить что-то об отключенной загрузке классов, поэтому я думаю, что проблема где-то там ... Спасибо!

4 ответов


загрузка удаленного класса может быть сложной.

исходное сообщение не содержит никакой информации о базе кода. Возможно, конфигурация безопасности клиента верна, но у нее нет доступа к удаленному коду. Классы загружаются клиентом непосредственно из "базы кода". Они не представляются клиенту службой через соединение RMI. Служба просто ссылается на внешний источник для классов.

сервер должен указать системное свойство java.rmi.server.codebase. Значение должно быть URL это доступно клиенту, из которого могут быть загружены необходимые классы. Если это file: URL, файловая система должен быть доступен для клиента.

и наоборот: если сервер должен иметь возможность загружать классы из клиента (например, здесь), клиент должен установить базовое свойство кода на URL-адрес, доступный серверу.


каждый раз, когда вы вызываете метод на динамическом прокси-сервере RMI,MarshalInputStream (который расширяет ObjectInputStream переопределить resolveClass и resolveProxyClass) делегатов LoaderHandler искать в 3 местах для ClassLoader использование:

  1. загрузчик классов вызываемого прокси (технически он использует Хак под названием latestUserDefinedLoader(): он идет вверх по стеку, ищу первый метод в стеке, который не является частью среда JRE.)
  2. Thread-local contextClassLoader абонента
  3. загрузчик классов кодовой базы, если SecurityManager включен
    1. если системное свойство java.rmi.server.useCodebaseOnly=false, затем загрузчик классов кодовой базы использует URL-адреса в пульт ДУ java.rmi.server.codebase. Обратите внимание, что значение по умолчанию useCodebaseOnly изменено в JDK 7u21 так что удаленная кодовая база больше не используется, если вы ее не измените!
    2. в противном случае загрузчик классов кодовой базы использует URL-адреса в местные java.rmi.server.codebase.

таким образом, есть несколько возможных причин, по которым вы получите ClassNotFoundException при вызове удаленного метода:

  • если стек содержит "No security manager: RMI class loader disabled", то обязательно установите SecurityManager, как описано другими, Если вам нужна удаленная загрузка классов для обеих сторон, чтобы получить все удаленные интерфейсы и сериализуемые классы.
  • если вы используете удаленный класс загрузка и он перестал работать при обновлении до JRE 7u21, а затем либо установить -Djava.rmi.server.useCodebaseOnly=true чтобы соответствовать предыдущему поведению или установить -Djava.rmi.server.codebase в разделенный пробелом список URL-адресов как на локальной, так и на удаленной сторонах. И убедитесь, что компьютер может получить доступ к этим url.
  • если вы используете пользовательский загрузчик классов локально, Родительский загрузчик классов которого определяет некоторые удаленные интерфейсы, затем обязательно позвоните Thread.setContextClassLoader(ClassLoader) так что RMI будет использовать этот загрузчик классов. (Это была моя проблема: у меня был SwingWorker это было запланировано на рабочий поток, который был создан до того, как contextClassLoader был установлен на EventDispatchThread). Например, A и C принадлежат вашему пользовательскому загрузчику классов, но B принадлежит родительскому загрузчику классов, а затем при вызове a.getB ().getC (), вызов getB() будет использовать пользовательский загрузчик классов, но вызов getC () не сможет найти C в latestUserDefinedClassLoader и должен будет вернуться к contextClassLoader.

все это предостерегающая история о плохом дизайне API ObjectInputStream. ObjectInputStream должен был потребовать от Вас передать параметр ClassLoader, а не пытаться найти его случайно, используя latestUserDefinedLoader, contextClassLoader и codebase.


требуется менеджер по безопасности на стороне сервера, а не только на стороне клиента.

без этого движок RMI сервера отказывается загружать классы от клиента, поскольку он не может гарантировать, что они не будут делать злых вещей на сервере.

вам нужна загрузка класса RMI вообще? Не может ли сервер уже иметь классы, которые клиент пытается отправить?


Я знаю, почему это происходит. например, вы запускаете сервер в проекте A, но вы используете клиент в проекте B для запроса этого сервера, это неправильно. Таким образом, вы должны поместить сервер и клиент в один проект.