2017-01-26 16 views
0

У меня есть проблема, связывающая удаленный объект с реестром RMI. Я сократил свой код до очень простого примера, который отлично работает, когда я тестирую его на своем компьютере (Windows 10). Но если я начну его на другом компьютере (Windows 7), когда registry.bind(id, remoteObject); вызывается, я получаю это исключение:Сбой связи RMI с «Нет менеджера безопасности: загрузчик класса RMI отключен»

java.lang.ClassNotFoundException: 
rmitest.IRemote (no security manager: RMI class loader disabled) 

я не нужен SecurityManager, так как все файлы классов находятся в банке, и я не хотите использовать функцию загрузки динамического кода.

Почему он пытается загрузить менеджера безопасности и почему он не может его найти, даже если я его определю? Что может быть причиной того, что он работает на одной машине, но не другой? Я думаю, что код в порядке, и он должен иметь некоторые проблемы с настройкой, но я не уверен, что именно настроено неправильно.

Вот удаленный интерфейс и реализация удаленных объектов, которые я экспортировал как исполняемый Jar в Eclipse как rmitest.jar.

public interface IRemote extends Remote { 
    void foo() throws RemoteException; 
} 
public class RemoteImpl extends UnicastRemoteObject implements IRemote { 

    private static Registry  registry; 

    public RemoteImpl() throws RemoteException { 
     super(); 
    } 

    public static void main(final String[] args) throws Exception { 
     try { 
      LocateRegistry.createRegistry(Registry.REGISTRY_PORT); 
     } catch (final Exception e) { 
      // already created 
     } 
     registry = LocateRegistry.getRegistry(Registry.REGISTRY_PORT); 
     registry.bind(UUID.randomUUID().toString(), new RemoteImpl()); 
     System.out.println("Binding successful"); 
    } 

    @Override 
    public void foo() throws RemoteException { 
     System.out.println("foo"); 
    } 
} 

Вот полный трассировки стека, она бросает в строке, где registry.bind вызывается и точно так же при работе с одной из следующих команд: java -jar rmitest.jar или
java -Djava.security.manager -Djava.security.policy=policy -jar rmitest.jar

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

Exception in thread "main" java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: rmitest.IRemote (no security manager: RMI class loader disabled) 
    at sun.rmi.server.UnicastServerRef.oldDispatch(Unknown Source) 
    at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) 
    at sun.rmi.transport.Transport$1.run(Unknown Source) 
    at sun.rmi.transport.Transport$1.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.rmi.transport.Transport.serviceCall(Unknown Source) 
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) 
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) 
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$256(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:276) 
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:253) 
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:379) 
    at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source) 
    at rmitest.RemoteImpl.main(RemoteImpl.java:29) 
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: rmitest.IRemote (no security manager: RMI class loader disabled) 
    at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source) 
    at sun.rmi.server.UnicastServerRef.oldDispatch(Unknown Source) 
    at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) 
    at sun.rmi.transport.Transport$1.run(Unknown Source) 
    at sun.rmi.transport.Transport$1.run(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.rmi.transport.Transport.serviceCall(Unknown Source) 
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) 
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) 
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$256(Unknown Source) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: java.lang.ClassNotFoundException: rmitest.IRemote (no security manager: RMI class loader disabled) 
    at sun.rmi.server.LoaderHandler.loadProxyClass(Unknown Source) 
    at java.rmi.server.RMIClassLoader$2.loadProxyClass(Unknown Source) 
    at java.rmi.server.RMIClassLoader.loadProxyClass(Unknown Source) 
    at sun.rmi.server.MarshalInputStream.resolveProxyClass(Unknown Source) 
    at java.io.ObjectInputStream.readProxyDesc(Unknown Source) 
    at java.io.ObjectInputStream.readClassDesc(Unknown Source) 
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) 
    at java.io.ObjectInputStream.readObject0(Unknown Source) 
    at java.io.ObjectInputStream.readObject(Unknown Source) 
    ... 15 more 

Вот файл политики, который должен позволить все:

grant { 
    permission java.security.AllPermission; 
}; 
+0

It * does not * 'пытается загрузить диспетчера безопасности, и здесь ничего нет, что предполагает иное. Он пытается загрузить ваш * класс * и не находит его. Не подходите к выводам. – EJP

+0

@EJP Я хотел сказать, что «ожидает, что диспетчер безопасности будет присутствовать», поскольку я интерпретирую сообщение exeption, чтобы предположить, что отсутствующий менеджер безопасности является причиной того, почему класс не может быть загружен. – Kapep

+0

Ну, это не означает ни одну из этих вещей. Это * note *, что диспетчер безопасности не работает. Не причина. – EJP

ответ

1

Проблема была «некоторый другой процесс Java» , в котором содержался его собственный Registry,, у которого не было доступа к вашему CLASSPATH. Вы бы обнаружили, что если бы у вас было что-то лучше, чем пустой блок catch для createRegistry().

+0

Да, пустой блок блокировки - это зверство, которого я не должен был делать - но я реплицировал проблему и зарегистрировал исключение, и он всегда точно такой же: 'java.net.BindException: Address уже используется: JVM_Bind', независимо от того, реестр имеет доступ к пути к классам или нет. – Kapep

+0

В любом случае, мне кажется, что я должен избегать использования 'createRegistry' в порту по умолчанию, если я не могу быть уверен, что другое приложение еще не создало реестр на этом порту? – Kapep

+0

Ваш первый комментарий не имеет смысла.«BindException» означает, что в другом JVM уже запущен другой Registry, а последующее «ClassNotFoundException» означает, что этот реестр не имел того же CLASSPATH, что и ваша JVM. Если вы не получите 'BindException', вы также не получите' ClassNotFoundException'. – EJP

1

Проблема была в какой-то другой Java работает процесс, который, казалось, INTERFER с привязкой реестра. Я не знаю, что именно сделал этот процесс изгоев, но убил его, разрешив ошибку. Никакой менеджер безопасности не нужен и просто запускать банку, как обычно, сейчас.