据我所知,RMI注册表维护一种HashMap数据结构,该数据结构存储名称和存根映射,其中存根本质上是一个对象 - 我们在调用Naming.lookup()
时得到的结果。
当我从具有存根类文件的目录启动remiregistry时,一切正常。绑定正确发生。但如果我没有启动远程服务 -
public static void main(String args[])
{
try {
GreeterService greeterService = new GreeterServiceImpl();
Naming.rebind("greeterServiceObj", greeterService);
} catch (Exception e) {
e.printStackTrace();
}
}
我得到了例外 -
C:\Users\athakur\newJavaWorkspace\RMIDemo\src>java GreeterServiceImpl
java.rmi.ServerException: RemoteException occurred in server thread; nested exception
is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception i
s:
java.lang.ClassNotFoundException: GreeterServiceImpl_Stub
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:400)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
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.j
ava: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(Unknown Sour
ce)
at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
at sun.rmi.server.UnicastRef.invoke(Unknown Source)
at sun.rmi.registry.RegistryImpl_Stub.rebind(Unknown Source)
at java.rmi.Naming.rebind(Unknown Source)
at GreeterServiceImpl.main(GreeterServiceImpl.java:19)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exceptio
n is:
java.lang.ClassNotFoundException: GreeterServiceImpl_Stub
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:390)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:248)
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
答案 0 :(得分:3)
为什么rmiregistry需要存根类文件?
因为它只是另一个RMI服务器,并且遵循与其他RMI服务器和客户端相同的语义。
我看到的那个解组错误是什么?
如果它将一个参数传递给没有该类可用的服务器,那么任何其他RMI客户端都会获得完全相同的异常。
即使rmiregistry无法解组UnicastRemoteObject导出的存根,也不应该rmiregistry记录该错误吗?
不,因为RMI注册表甚至没有看到它。在注册表代码执行之前,所有这些都发生在RMI运行时,同时还会调用该调用。事实上,注册表代码根本没有执行过。