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$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;
}

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

26
задан Mark 27 October 2016 в 17:04
поделиться

3 ответа

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

-3
ответ дан 28 November 2019 в 07:42
поделиться

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

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

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

4
ответ дан 28 November 2019 в 07:42
поделиться

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

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

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

  • Если в стеке нет «диспетчера безопасности: Загрузчик классов RMI отключен », а затем обязательно установите SecurityManager, как описано другими, если вам требуется удаленная загрузка классов для обеих сторон, чтобы получить все интерфейсы Remote и сериализуемые классы.
  • Если вы используете удаленную загрузку классов и она перестала работать при обновлении до JRE 7u21, то либо установите -Djava.rmi.server.useCodebaseOnly=true в соответствии с предыдущим поведением, либо установите -Djava.rmi.server.codebase в список разделенных пробелами списков URL как на локальном, так и на локальном отдаленные стороны. И убедитесь, что компьютер может получить доступ к этим URL.
  • Если вы используете пользовательский ClassLoader локально, родительский загрузчик которого определяет некоторые удаленные интерфейсы, то обязательно вызовите 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.

7
ответ дан 28 November 2019 в 07:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: