RMI原理浅析
来源:互联网 发布:curl json 编辑:程序博客网 时间:2024/06/18 13:57
之前看过一个RMI的简单示例。这篇文章简单的分析一下RMI的原理。
RMI应用程序的体系结构
上一个例子中,我们编写了两个程序,一个服务端(Server)和一个客户端(Client)。
- 在Server内创建一个远程对象(CalcServiceImpl),并生成存根,注册到Registry中。
- 客户端请求远程对象,并调用对象的方法。
- Transport Layer:RMI传输层实现网络连接与通信的数据传递。
- Stub:存根是远程对象在客户端的代理,它驻留在客户端系统中,充当客户端程序的网关。
- Skeleton:骨架驻留在服务端系统中,Stub通过Skeleton传递参数给远程服务对象。
- RRL(Remote Reference Layer):RRL是负责管理客户端到远程对象的引用。
RMI的工作原理
- 当客户端调用远程对象时,它会被Stub接收,并把请求传递给RRL
- 当客户端RRL接收到请求后,它会调用RemoteRef的invoke()方法。最终这个请求会被传递到服务端的RRL中。
- 服务端RRL将请求发给Skeleton(服务端的一个代理类),最终调用服务端中的服务对象方法。
- 服务方法返回的结果按原路返回给客户端。
Marshalling与Unmarshalling
当客户端调用远程对象的方法时,可能需要传递一些参数。这些参数将会被包装在消息中通过网络发送给服务端。这些参数会被序列化成二进制数据流传输到服务端,这个过程也被叫做Marshalling;相反服务端需要把二进制数据流反序列化还原,这个过程也被叫做Unmarshalling。
事实上这两个过程使用的使我们非常熟悉的ObjectOutputStream和ObjectInputStream。只不过,RMI进一步包装了这两个类:
这两个过程之间涉及到的消息通信协议,也被称为JRMP协议,Java Remote Message Protocol
RmiRegistry的作用
RmiRegistry用于管理所有的远程服务。
服务器端创建对象时,都会使用Registry.bind
或Registry.rebind
方法向RmiRegistry注册对象。每个服务对象都对应着一个唯一的服务名。
客户端调用远程对象时,客户端需要远程对象的引用。客户端可以根据服务名调用Registry.lookup
方法从RmiRegistry中获取对象。
分析Stub中的源代码
在上面的体系架构中,提到了Stub与Skeleton,但是在程序中我们并没有看到这两个类,那是因为从Java 5.0之后,Java使用java.lang.reflect.Proxy
为我们动态生成了这两个类。
service.getClass()
打印得到的是:class com.sun.proxy.$Proxy0
在Java 5.0之前需要我们使用rmic
命令根据服务实现类编译生成存根。
# -keep选项:保留生成的源代码rmic -keep cn.hff.service.CalcServiceImpl
生成源码的Stub对象如下:
// Stub class generated by rmic, do not edit.// Contents subject to change without notice.package cn.hff.service;public final class CalcServiceImpl_Stub extends java.rmi.server.RemoteStub implements cn.hff.service.ICalcService { private static final long serialVersionUID = 2; private static java.lang.reflect.Method $method_add_0; private static java.lang.reflect.Method $method_minus_1; static { try { // 获取add方法 $method_add_0 = cn.hff.service.ICalcService.class.getMethod("add", new java.lang.Class[] { int.class, int.class }); // 获取minus方法 $method_minus_1 = cn.hff.service.ICalcService.class.getMethod("minus", new java.lang.Class[] { int.class, int.class }); } catch (java.lang.NoSuchMethodException e) { throw new java.lang.NoSuchMethodError("stub class initialization failed"); } } // constructors // 创建CalcServiceImpl_Stub时需要指定RemoteRef // RemoteRef就是远程对象的引用 public CalcServiceImpl_Stub(java.rmi.server.RemoteRef ref) { super(ref); } // methods from remote interfaces // implementation of add(int, int) public int add(int $param_int_1, int $param_int_2) throws java.rmi.RemoteException { try { /** * @param obj:包含RemoteRef的存根对象 * @param method:被调用的方法 * @param params:方法的参数 * @param opnum:被调方法的哈希值 * @return result:返回结果 */ Object $result = ref.invoke(this, $method_add_0, new java.lang.Object[] { new java.lang.Integer($param_int_1), new java.lang.Integer($param_int_2) }, -7734458262622125146L); return ((java.lang.Integer) $result).intValue(); } catch (java.lang.RuntimeException e) { throw e; } catch (java.rmi.RemoteException e) { throw e; } catch (java.lang.Exception e) { throw new java.rmi.UnexpectedException("undeclared checked exception", e); } } // implementation of minus(int, int) public int minus(int $param_int_1, int $param_int_2) throws java.rmi.RemoteException { try { Object $result = ref.invoke(this, $method_minus_1, new java.lang.Object[] { new java.lang.Integer($param_int_1), new java.lang.Integer($param_int_2) }, 6403391039451205508L); return ((java.lang.Integer) $result).intValue(); } catch (java.lang.RuntimeException e) { throw e; } catch (java.rmi.RemoteException e) { throw e; } catch (java.lang.Exception e) { throw new java.rmi.UnexpectedException("undeclared checked exception", e); } }}
RemoteRef的实现类UnicaseRef的源码可以点击这里查看。
- RMI原理浅析
- RMI--原理及实现浅析
- RMI(Remote Method Invocation)原理浅析
- RMI(Remote Method Invocation)原理浅析
- RMI(Remote Method Invocation)原理浅析
- RMI(Remote Method Invocation)原理浅析
- RMI 浅析
- RMI原理
- 【J2EE浅析】——RMI
- RMI原理及实现
- RMI原理及实现
- RMI原理及实现
- RMI原理及实现
- RMI原理与示例
- RMI的工作原理
- Java RMI原理
- EJB理解------RMI原理
- java RMI原理解析
- 蓝桥杯vip题 分解质因素
- Unity 物理系统
- java学习 2017-12-23
- 知识点小积累
- Python原创第十篇~字符串
- RMI原理浅析
- shell脚本-批量建立用户user_01,user_02...user_100
- 【剑指**】7.重建二叉树
- 程序员怎么写代码和学习新技术
- CSS3 用户界面
- linux系统编程之高级IO
- 自己的网页加载天气
- Shader屏幕后處理效果
- CodeForces 57 C.Array(组合数学)