RMI应用程序通常由两个独立的程序构成:一个server和一个client。一个典型的server应用程序创建一些远程对象,使它们可被引用,并等待客户端调用这些远程对象的方法。一个典型的client应用程序得到server上的一个或多个远程对象的远程引用,并调用这些对象的方法。RMI提供了server和client通信和传递信息的机制。这样的应用程序叫做一个分布式对象应用程序。

  分布式对象应用程序需要定位远程对象:应用程序可以使用两种机制之一来获得远程对象的引用。应用程序可以使用RMI的命名工具rmiregistry来注册它的远程对象,或者象进行一般操作一样传递和返回远程对象的引用。

  和远程对象通信:远程对象之间的通信细节由RMI来处理。对程序员来说,远程通信就像一个标准的Java方法调用。
  
  装载被传递对象的类字节码:因为RMI允许调用者向远程对象传递对象,所以它提供了传递数据和装载一个对象代码的必要机制。

  下图描述了一个使用注册机制获得一个远程对象引用的RMI分布式应用程序。Server方调用注册器将一个远程对象和一个名字联系起来。Client方在Server的注册器中通过名字寻找远程对象并调用其方法。该图也显示了RMI系统使用一个现有web server来装载类字节码,在需要时在server和client之间传输字节码。



  RMI的一个重要而独特的特性是它能动态下载一个在接收者的虚拟机中未定义的对象类的字节码(或简单代码)。一个对象的类型和行为,这些原来只能在一个单一的虚拟机中可以得到的信息,可以被传递给另一个可能是远程的虚拟机。RMI将对象连同其真实的类型一起传递,所以当这些对象被传递给另一个虚拟机时其行为不发生改变。这就允许将新类型引入一个远程的虚拟机,从而动态扩展一个应用程序的行为。

  像其他应用程序一样,一个使用Java RMI的分布式应用程序也由接口和类组成。接口中定义一些方法,类实现接口中定义的方法,并定义一些其他的方法。在一个分布式应用程序中,一些实现需要驻留在不同的虚拟机上。具有可以跨虚拟机调用的方法的对象叫做远程对象。一个对象通过实现一个远程接口成为远程对象,它具有如下特征:

  1) 一个远程接口由java.rmi.Remote派生。

  2) 接口中的每个方法都要声明抛出java.rmi.RemoteException,除了 其他特殊的例外之外。
  当对象从一个虚拟机传递给另一个虚拟机时,RMI对远程对象的处理与非远程对象是不相同的。对于远程对象,RMI传递给接收方虚拟机一个远程端头,而不是一个对象的拷贝。端头作为远程对象的本地标识或代理,对于调用方来说,是一个远程引用。调用方调用本地端头的一个方法,由本地端头负责处理对远程对象的方法调用。

  一个远程对象的端头实现了与远程对象实现的相同的接口。这就允许一个端头可以被转换为远程对象所实现的任意一个接口。这也意味着只有定义在远程接口中的方法才可以在接收方虚拟机上被调用。

  当你使用RMI来开发一个分布式应用时,需要遵守下面的步骤:

  1) 设计和实现你的分布式应用的组件。
  首先,决定应用程序的结构,哪些组件是本地对象,哪些应该可以远程访问。这个步骤包括:

  定义远程接口:一个远程接口定义了可以被客户端远程调用的方法。客户端针对远程接口编程,而不是针对实现这些接口的类。设计这样的接口的一部分工作取决于作为这些方法的参数和返回值的本地对象。如果还没有这样的接口和类的存在,就需要自己定义。

  实现远程对象:远程对象必须实现一个或多个远程接口。远程对象类可能包括其他接口(本地的或远程的)和方法(仅在本地可得到的)的实现。如果有本地类作为这些方法的参数或返回值,这些类也必须被实现。
实现客户端:使用远程对象的客户可以在远程接口被定义后的任何时候实现,包括远程对象被展开后。

  2) 编译源程序并生成端头。  
  这是一个两步操作过程。第一步,使用Javac编译器来编译源文件,其中包含了远程接口及其实现部分、server类和client类。第二步,使用rmic编译器来生成远程对象的端头。RMI使用一个远程对象的端头类来作为客户端的代理,从而使客户端可以同一个特定的远程对象通信。

  3) 使得类可以通过网络访问。
  这一步使一切与远程接口有关的类文件、端头、其他任意的需要下载到客户方的类可以通过一个web server访问。

  4) 启动应用程序。
  启动应用程序包括运行RMI远程对象注册程序,服务器,客户端。

  用RMI来构造分布式应用系统是不是很简单的一件事情?的确,RMI使我们可以自己编写分布式的应用系统,在没有RMI之前这种事情是难于想象的。