我在两台机器上设置了一个 RMI 客户端/服务器,当服务器不需要客户端定义的类时,它们在简单的情况下工作正常。但是,当我需要使用在客户端定义的类时,我无法让服务器解组这些类。我怀疑这是我java.rmi.server.codebase
作为参数传递给客户端应用程序的属性的问题。我遵循了 Sun 的 RMI 教程跟踪,我认为我已经完全遵循了这些步骤,只是在执行客户端和服务器时我没有指定类路径参数,因为它们在根包目录正上方的目录中执行(但是我也尝试过没有影响)。
我在尝试执行下面详细描述的不同客户端组合时遇到的异常都是相同的:
RmiServer exception:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: test.MyTask
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:353)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)
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 java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
at $Proxy0.execute(Unknown Source)
at test.myClient.main(myClient.java:32)
详情如下:
我的客户端/服务器 rmi 设置在路由器后面的家庭网络上。路由器分配给我将调用的静态 IP 地址myhostname
。在指向正确机器的路由器中设置了适当的端口映射。
角色、机器、操作系统、IP 地址:
server, venice, linux ubuntu 9.10, 10.0.1.2
client, naples, mac os x leopard, 10.0.1.4
我在里面启动服务器端如下/home/andrews/workspace/epsilon/bin
:
1 在默认端口 1099 上启动注册表:
venice% rmiregistry &
2 在端口 2001 上启动 Web 服务器,指向通用接口的代码库:
venice% java webserver/ClassFileServer 2001 /home/andrew/workspace/epsilon/bin
3 注册服务器对象的启动服务器应用程序(test/myServer 中的主类):
venice% java -Djava.rmi.server.codebase="http://myhostname:2001/" -Djava.security.policy=server.policy -Djava.rmi.server.hostname=myhostname test/myServer &
现在里面的客户端/Users/andrews/Development/Java/workspace/epsilon/bin
:
1启动一个本地Web服务器,可以将客户端类服务器提供给服务器(不确定是否需要,但我添加了我尝试过,但仍然没有成功;我已将端口映射添加到2001的路由器到venice
,对于2002 年至naples
)
naples$ java webserver/ClassFileServer 2002 /Users/andrews/Development/Java/workspace/epsilon/bin/
尝试运行客户端(注意:我没有指定-cp
参数,因为客户端在根包目录的正上方执行):
1 使用 http 主机名尝试 #1
naples$ java -Djava.rmi.server.codebase=http://10.0.1.4:2002/ -Djava.security.policy=client.policy test.myClient myhostname
注 1:最后的myhostname
参数传递给客户端,以便它解析为服务器的 rmi 主机名。
注意2:我也尝试过使用localhost:2002
而不是10.0.1.4:2002
。
注意 3:我尝试使用myhostname:2002
因为myhostname
分配给路由器并且我有正确的端口映射设置,这个地址应该解析为naples
而不是venice
2尝试#2:
naples$ java -Djava.rmi.server.codebase=file:/Users/andrews/Development/Java/workspace/epsilon/bin/ -Djava.security.policy=client.policy test.myClient myhostname
注1:代码库url格式是正确的,我创建了一个小程序将当前文件目录路径转换为url并使用它。使用file:///Users...
具有相同的效果。
其他注意事项:
1 我的服务器和客户端策略文件正确指定了路径,因为我已经用好的和坏的路径测试了这个设置,并且得到了坏路径的安全异常
2 如果我不使用客户端定义的对象,则此设置有效,客户端正确连接到服务器并且服务器执行。
3 当我将客户端类放在服务器的类路径中的服务器上时,一切正常。
感谢所有帮助。