为什么RMI注册表需要访问存根类文件?

时间:2015-02-14 15:46:28

标签: java rmi stub

据我所知,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
  1. 为什么rmiregistry需要存根类文件?
  2. 我看到的那个解组错误是什么?即使rmiregistry无法解组UnicastRemoteObject导出的存根,也不应该记录该错误吗?

1 个答案:

答案 0 :(得分:3)

  

为什么rmiregistry需要存根类文件?

因为它只是另一个RMI服务器,并且遵循与其他RMI服务器和客户端相同的语义。

  

我看到的那个解组错误是什么?

如果它将一个参数传递给没有该类可用的服务器,那么任何其他RMI客户端都会获得完全相同的异常。

  

即使rmiregistry无法解组UnicastRemoteObject导出的存根,也不应该rmiregistry记录该错误吗?

不,因为RMI注册表甚至没有看到它。在注册表代码执行之前,所有这些都发生在RMI运行时,同时还会调用该调用。事实上,注册表代码根本没有执行过。