Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Работа с сетью > RMI-JNDI Ошибка при доступе к InitialContext


Автор: shoura 31.1.2008, 15:18
Вот код, для запуска RMI сервера, с некоторыми проверками:
Код

package localhost.test.rmi.server;

import ....;

public class Launcher {
  public static void main(String[] args){
    try {
      Class.forName("localhost.test.rmi.server.MessageServiceImpl_Stub"); // работает

      URL[] urls = new URL[]{new URL("file://D:/other/home/projects/test/build")};
      URLClassLoader loader = URLClassLoader.newInstance(urls);
      Class c1 = loader.loadClass("localhost.test.rmi.server.MessageServiceImpl_Stub");
      Constructor constr = c1.getConstructor(java.rmi.server.RemoteRef.class); // аналогично работает

      MessageServiceImpl msgServer = new MessageServiceImpl();
      MessageService msgSvc = (MessageService)UnicastRemoteObject.exportObject(msgServer);
      Hashtable<String, String> props = new Hashtable<String, String>();
      props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");
      props.put(Context.PROVIDER_URL, "rmi://localhost:1099");
      Context c = new InitialContext(props); // падает Exception
      c.rebind(RmiNameRegistry.MSG_SERVICE, msgSvc);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}



с помощью rmic создана необходимая заглушка localhost.test.rmi.server.MessageServiceImpl_Stub, находится в класспаче

содержимое файла server.policy:

grant codeBase "file:${{java.ext.dirs}}/*" {
permission java.security.AllPermission;
};

grant codeBase "file://D:/other/home/projects/test/build/*" {
permission java.security.AllPermission;
};

grant {  
    permission java.security.AllPermission;
};


rmiregistry запущен на 1099 порту

Запускаем:

java -Djava.naming.factory.initial=com.sun.jndi.rmi.registry.RegistryContextFactory -Djava.security.policy="D:\other\home\projects\test\server.policy" -Djava.naming.provider.url=rmi://localhost:1099 -cp D:\other\home\projects\test\build  localhost.test.rmi.server.Launcher

Имеем:

javax.naming.CommunicationException [Root exception is java.rmi.ServerException:
 RemoteException occurred in server thread; nested exception is:
        java.rmi.UnmarshalException: error unmarshalling arguments; nested excep
tion is:
        java.lang.ClassNotFoundException: localhost.test.rmi.server.MessageServi
ceImpl_Stub]
        at com.sun.jndi.rmi.registry.RegistryContext.bind(Unknown Source)
        at com.sun.jndi.rmi.registry.RegistryContext.bind(Unknown Source)
        at javax.naming.InitialContext.bind(Unknown Source)
        at localhost.test.rmi.server.Launcher.main(Launcher.java:41)
Caused by: java.rmi.ServerException: RemoteException occurred in server thread;
nested exception is:
        java.rmi.UnmarshalException: error unmarshalling arguments; nested excep
tion is:
        java.lang.ClassNotFoundException: localhost.test.rmi.server.MessageServi
ceImpl_Stub
        at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:385
)
        at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)
        at sun.rmi.transport.Transport$1.run(Transport.java:153)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:4
60)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport
.java:701)
        at java.lang.Thread.run(Thread.java:595)
        at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknow
n Source)
        at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
        at sun.rmi.server.UnicastRef.invoke(Unknown Source)
        at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source)
        ... 4 more
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested ex
ception is:
        java.lang.ClassNotFoundException: localhost.test.rmi.server.MessageServi
ceImpl_Stub
        at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
        at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:375
)
        at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)
        at sun.rmi.transport.Transport$1.run(Transport.java:153)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
        at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:4
60)
        at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport
.java:701)
        at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.ClassNotFoundException: localhost.test.rmi.server.MessageSe
rviceImpl_Stub
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:242)
        at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:430)
        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.jav
a:197)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:153
8)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1460)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1
693)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:339)
        ... 9 more

Помогите разобраться, что может быть не так?

Автор: shoura 31.1.2008, 15:46
Уточняю вызов программы:

java -Djava.security.manager -Djava.security.policy="D:\other\home\projects\test\server.policy" -cp D:\other\home\projects\test\build  localhost.test.rmi.server.Launcher

По сути это ничего не меняет, ошибка та же

Автор: shoura 31.1.2008, 17:55
Вообще-то проблема странная, в моем случае:

Код

Naming.rebind("rmi://localhost:10999/" + RmiNameRegistry.MSG_SERVICE, msgServer);


тоже отказалось работать с той же ошибкой

Однако в случае LocateRegistry.createRegistry(1099);

указанный выше пример работает и через JNDI и через Naming
уж не знаю на что и думать  smile 

Автор: shoura 1.2.2008, 10:38
Проблема решена:

Кому интересно может глянуть http://www.jguru.com/faq/view.jsp?EID=396598.

Проблема в том что RMI registry использует RMIClassLoader на основе URLClassLoader, которому необходимо получить доступ к заглушке для ее десериализации. Для этого можно положить Jar с соотв. заглушками в катало {java.home}/bin, либо что лучше, добавить параметр окружения java.rmi.server.codebase при регистрации сервера в виде:

Код

System.setProperty("java.rmi.server.codebase", "file://localhost/d:/other/home/projects/test/build/");


или 

Код

-Djava.rmi.server.codebase=file://<IP>/<Drive-Letter>:/<Path to the root directory of your packages>/ <Class with main>


в моем случае помогло это:

Код

java -Djava.rmi.server.codebase=file://localhost/d:/other/home/projects/test/build/ localhost.test.rmi.server.Launcher

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)