Troubles in RMI

原创 2007年10月05日 00:18:00

 

 

前几天把一个RMI应用迁移到新的机器,之前这个应用运行在一台增强版的PC上。
新机器上面的环境“理论上”跟以前的环境是一样的,至少我是这样要求服务器管理员的。
用同样的shell启动应用,问题发生了,应用并没像在之前的环境那样正常的运行,查log发现报RMI Exception

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; 
nested exception is:
java.lang.ClassNotFoundException: XXX_Stub
XXX_Stub是RMI Server的Stub,其class文件跟应用的其他class文件包在同一个JAR里面,为什么新环境偏偏就找不到呢?
请教了Mr. Smith,发现许多人遇到了类似的问题,解法也是五花八门。
有人说是环境属性CLASSPATH没添加那个XXX_Stub所在的JAR的路径,造成RMI REGISTRY无法找到这个XXX_Stub。
于是在启动的shell里面添加
   
export CLASSPATH={path/to/JAR}
再次启动,不再报RMI Exception了,在新环境启动应用的Client测试RMI Server,一切正常。看来那位老兄说对了。
问题确认,再来检查新旧环境的user profile设置,果然发现新环境的user profile恰恰少了这个CLASSPATH的设定。在这里补上,就不用改启动的shell了。

不过接下来在另外一台机器上启动应用的Client测试RMI Server的时候却出现异常。
先还以为是新环境上charset的设置有问题,使RMI Server传回的xml中出现乱码,从而造成错误。
在这个方向上查了半天,还参考了车东大哥写的Java中文处理学习笔记 ,后来才发现并非charset方面的问题,因为即使RMI Server产生的是正确的xml,也不能正确的传回Client。于是回过头来查Client的log,在Debug Log中发现这么一个错误:
   
java.rmi.ConnectException: Connection refused to host: 127.0.0.1...
奇怪,Client明明设定去连Server的IP,怎么这里却变成了127.0.0.1?再次请教了史密斯先生,说是需要检查一下RMI Server所在环境的Linux /etc/hosts 中的设定。果然发现管理员兄弟“特地”把机器别名指向到了127.0.0.1,类似如下这样的格式
127.0.0.1   localhost.localdomain   localhost   hostalias
{true_ip}   hostalias

把第一行最后那个多余的hostalias拿掉,重启RMI Server,Client便可正常连接并操作了。

搞定收工!!

小结一下处理这次麻烦的体会。
  1. 基于RMI开发出来的应用在易用性上不如基于其他部分的Java平台的应用。特别是涉及到应用的跨平台迁移,比如Windows <--> Linux,则有许多牵涉到OS层面的设定问题。如针对RMI REGISTRY的CLASSPATH的设定,Linux上面etc/host 的设定。这些细节稍不留意,应用就无法正常运行,原因还不易发现。
  2. 借此机会复习了RMI 的通信模型:先是RMI Server向RMI REGISTRY注册并提交Stub,于是RMI Client就可在RMI REGISTRY中查找RMI Server的确切位置并下载Stub,最后RMI Client就依获取的Stub及RMI Server的确切位置跟RMI Server建立连接并执行操作。这次遇到的问题实际上都跟RMI REGISTRY有关。第1个问题是因为RMI REGISTRY在注册的时候没找到RMI Stub的确切位置,第2个问题则源于RMI REGISTRY在Linux上才会有的表现,当RMI Client向其查询RMI Server的确切位置的时候,它会去查 /etc/hosts 中的设定,并试图返回OS层面所设定的IP。自己对其中具体的逻辑还不了解,不过可以肯定的是,如果 /etc/hosts中设定错了,RMI Client将无法得到的正确的RMI Server的位置。
  3. 费了许多心思才把问题搞定,这次一定要让“粗心”的管理员兄弟请客!哈哈。
  4. 或许...我也要请一下这位兄弟的。

--END
 

浅谈RMI - 搭建一个简单的RMI程序

RMI是Remote Method Invoke的缩写,是JDK提供的一个完善的、简单易用的远程调用框架,它要求客户端和服务器端都是Java程序。下面简述RMI的基本原理:如下图所示,RMI采用代理来...
  • xiaoyaoyulinger
  • xiaoyaoyulinger
  • 2016年05月19日 11:50
  • 2274

Java RMI之HelloWorld程序以及相关的安全管理器的知识

Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方...
  • wjrong_1
  • wjrong_1
  • 2015年07月22日 16:38
  • 1471

java RMI原理详解

定义 RMI(Remote Method Invocation)为远程方法调用,是允许运行在一个Java虚拟机的对象调用运行在另一个Java虚拟机上的对象的方法。 这两个虚拟机可以是运行在相同计算机上...
  • xinghun_4
  • xinghun_4
  • 2015年05月17日 19:16
  • 7646

RMI和socket详解

详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp58   一般来说,基于CS(client-server)软件架构的开...
  • yemou_blog
  • yemou_blog
  • 2015年12月14日 11:17
  • 594

java rmi服务器端客户端传输数据实例教程

java rmi服务器端客户端传输数据实例教程 java代码下载地址:http://www.zuidaima.com/share/1550463269620736.htm...
  • yaerfeng
  • yaerfeng
  • 2014年07月19日 10:56
  • 4249

远程通信的几种选择(RPC,Webservice,RMI,JMS的区别)

RPC(Remote Procedure Call Protocol) RPC使用C/S方式,采用http协议,发送请求到服务器,等待服务器返回结果。这个请求包括一个参数集和一个文本集,通常形成“cl...
  • shan9liang
  • shan9liang
  • 2013年06月04日 10:31
  • 67705

docker命令之rmi

docker命令之rmi
  • u010822828
  • u010822828
  • 2015年02月03日 16:52
  • 1312

Eclipse 里面 用RMI 插件来编写 RMI server and client的实际例子

下面是通过一个实际例子来演示如何在Eclipse中安装RMI插件来编写RMIclient/server. 1) 下载RMI 插件到eclipse (luna R4.4.1) 从下面链接下载...
  • bigtree_3721
  • bigtree_3721
  • 2016年01月31日 20:18
  • 875

Java RMI实现以及Spring封装RMI实现小结

最近应用到了Java RMI技术,所以总结一下RMI的使用,另外EJB的实现也是以Java RMI为基础核心的。RMI远程方法调用,可以跨机器通过网络调用,不过Java RMI只支持两边都是Java程...
  • zmx729618
  • zmx729618
  • 2016年08月05日 16:53
  • 6909

如何在Spring框架中使用RMI技术

如何在Spring框架中使用RMI技术
  • wangshuxuncom
  • wangshuxuncom
  • 2015年01月25日 05:50
  • 2501
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Troubles in RMI
举报原因:
原因补充:

(最多只允许输入30个字)