实现远程方法调用设计几个独立的对象和模块。一个应用级对象A拥有一个远程对象B的引用,所以可以调用远程对象B的一个方法。本节将讨论图中每一个组件扮演的角色,首先讨论通信和远程引用模块,然后讨论运行在模块上面的RMI软件。
通信模块:两个相互协作的通信模块执行请求-应答协议,改协议在客户和服务器之间传递请求和应答消息。通信模块只是用请求应答消息的前三项,就是消息类型,requestID和被调用的远程对象的引用。operationId和所有的编码解码都与下面讨论的RMI软件有关。两个通信模块一起负责指定的调用语义,例如至多一次。
服务器端信息模块为被调用的类对象选择分发器,传输它的本地引用,该本地引用取自远程引用模块,用来替换请求消息中的远程对象标识符。
远程引用模块:远程引用模块负责在本地对象引用和远程对象引用之间进行翻译,负责创建远程对象引用。为了履行职责,每个进程中的远程引用模块都有远程对象表,该表记录着该进程的本地对象引用和远程对象引用的对应关系。
。该进程所有的远程对象。图中的远程对象B会记录在服务器端的表中。
。每个代理,B的代理会记录在客户端的表中。
远程引用模块的动作如下:
。当远程对象第一次作为参数或者结果传递时,远程引用模块创建一个远程对象引用,并把它添加到表中。
。当远程对象引用随请求或者应答消息到达时,远程引用模块要提供对应的本地对象的引用,它可能指向一个代理,也可能指向一个远程对象。若远程对象引用不在表中,那么RMI软件就创建一个新的代理并要求远程引用模块将它添加到表中。当RMI软件组件正在编码和解码的时候,这个远程对象引用模块被调用。例如,当请求消息到达时,可以使用这张表找出调用了哪个本地对象。
伺服器是一个提供了远程对象主体的类的实例。由相应的骨架传递的远程请求最终是由伺服器来处理的。伺服器存活于服务器进程中,当远程对象被实例化,就会生成一个伺服器,这些伺服器可以使用,直到不再需要远程对象为止,最终,伺服器也将作为无用的单元被回收或者删除。
RMI软件 它是由位于应用层和通信模块,远程引用模块之间的软件层组成,中间件对象有如下几个角色
代理:代理的作用是对调用者表现得就像调用本地对象一样,从而使远程方法调用对客户透明。它不执行调用,而是将调用放在消息里传递给远程对象。它隐藏了远程对象引用的细节,参数的编码,结果的解码,以及客户端消息的发送和接收。对于具有远程对象引用的进程,其中每个远程对象都有一个代理。代理类实现它代表的远程对象的远程接口定义的方法,这保证远程方法调用与远程对象的类型使匹配的。然而,代理实现他们的方式有很大的区别。代理中的每个方法会把一个目标对象的引用,它自身的methodid和它的参数编码进一个请求消息并发送给目标,然后等待应答消息,解码并将消息传回到调用者。
分发器:服务器对表示远程对象的每个类都有一个分发器和骨架。服务器有远程对象B的分发器和骨架。分发器接收来自通信模块的请求消息,并传递请求消息,并使用methodid选择骨架中恰当的方法。分发器和代理远程接口中的方法使用相同的methodid。
骨架:远程对象类有一个骨架,用于实现远程接口中的方法。这些方法与作为远程对象的主体伺服器的方法极为不同。一个骨架的方法将请求中的消息参数解码,并调用伺服器中相应的方法。它等待调用完成,然后将结果和异常信息编码进应答消息,传送给发送方代理的方法。
创建代理类,分发器和骨架。 在RMI中使用的代理类,分发器类和骨架类由接口编译器自动创建,
动态调用:可替换代理的选择。上面提到的代理是静态的,代理类通过接口定义生成的,并被表一到客户端的代码中,在一些情况下,这是不实际。如果一个远程调用指向了客户端程序中的对象,而这个对象的远程接口在编译时是不能确定的,这就需要在运行采用动态调用的方法。
动态骨架 :在上面的例子中,我们可以清楚地看到,服务器有时需要驻留那些在编译时尚不能确定的远程对象。
服务器和客户程序 服务器程序包含分发器类和骨架类,以及它支持的所有伺服器类的实现,另外,服务器程序包含初始化部分,初始化部分负责创建并初始化至少一个驻留在服务器上的伺服器,其余的伺服器可以应客户发出的请求而创建。初始化部分也可以用一个绑定程序注册它的一些伺服器。通常情况下,它只注册一个伺服器,该伺服器都可以用来访问其他对象。
客户程序会包含它将调用的所有远程对象的代理类,它用一个绑定程序查找远程对象引用。
工厂方法 远程对象接口不包含构造器。这意味着伺服器不能通过构造函数的远程调用来创建。伺服器可以在初始化部分创建,也可以在为该用途而设计的远程接口中创建。术语工厂方法有时指的是创建伺服器的方法,工厂对象指的是具有工厂方法的对象。任何远程对象,它要想能应客户的需求而创建新的远程对象,就必须在远程接口中提供用于此用途的方法。
绑定程序 客户程序通常要有一种手段,以便获得服务器至少一个远程对象的远程对象引用。
服务器线程 服务器一般为每个远程调用的执行分配一个独立的线程。这时,远程对辖区内高实现的设计者必须考虑到并发执行状态的影响。
为了避免因为在全部时间里运行管理这些远程对象的服务器造成潜在的资源浪费,服务器应该在客户需要他们的任何时候启动,启动用于驻留远程对象的服务器的进程被称为激活器。原因如下:
。当一个远程对象在一个运行的进程中可供调用时,就认为他是主动;如果它现在不是主动的但是可以激活为主动的,就认为它是被动的。一个被动的对象包括两个部分
。它的方法的实现
。它的编码格式的状态
持久对象的存储 在进程两次激活之间仍然保证存活的对象称为持久对象。持久对象一般由持久对象存储来管理。它在磁盘上以编码格式存储持久对象的状态。
判断一个对象是否是持久化对象的方法:
。任何可以通过持久根访问到的对象都被定义为持久的。
。持久对象存储提供的一些持久类
对象定位:定位服务帮助客户端根据远程对象引用定位