我在两台机器上设置了RMI客户端/服务器,当服务器不需要客户端定义的类时,它在一个简单的情况下工作正常。但是,当我需要使用客户端定义的类时,我无法让服务器解组这些类。我怀疑这是我的java.rmi.server.codebase
属性的问题,我将其作为参数传递给客户端应用程序。我遵循了Sun的RMI Tutorial路径,我认为我已经完全遵循了这些步骤,除了我在执行客户端和服务器时没有指定类路径参数,因为它们在根目录包目录正上方的目录中执行(但是我也试过了效果)。
尝试执行下面详细描述的不同客户端组合时,我得到的例外情况完全相同:
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
:
在默认端口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
而不是{{ 1}}
2尝试#2:
venice
naples$ java -Djava.rmi.server.codebase=file:/Users/andrews/Development/Java/workspace/epsilon/bin/ -Djava.security.policy=client.policy test.myClient myhostname
具有相同的效果。
其他说明:
1我的服务器和客户端策略文件正确指定了路径,因为我已经使用好路径和坏路径测试了此设置,并获得了错误路径的安全性异常
2如果我不使用客户端定义的对象,客户端正确连接到服务器并且服务器执行,则此设置有效。
3当我将客户端类放在服务器类路径中的服务器上时,所有都执行正常。
感谢所有帮助。
答案 0 :(得分:0)
你真的需要使用RMI吗?我和一个朋友在学校尝试了一次,它方式慢,比我们之前做过的简单的ObjectOutputStream网络要慢得多。
答案 1 :(得分:0)
我非常同意Chad Okere的说法,RMI实际上非常缓慢且耗费资源。有时直接使用套接字可能是简单而有用的选择,关于您的异常您能否确认您的rmi服务器正常工作? http://www.javarmi.com/2010/05/java-rmi-error-unmarshalling-arguments/也许可以帮到你