# RMI 应用程序概述

> 原文： [https://docs.oracle.com/javase/tutorial/rmi/overview.html](https://docs.oracle.com/javase/tutorial/rmi/overview.html)

RMI 应用程序通常包括两个单独的程序，即服务器和客户端。典型的服务器程序创建一些远程对象，可以访问这些对象，并等待客户端调用这些对象上的方法。典型的客户端程序获取对服务器上的一个或多个远程对象的远程引用，然后调用它们上的方法。 RMI 提供了服务器和客户端进行通信和来回传递信息的机制。这种应用有时被称为 _ 分布式对象应用 _。

分布式对象应用程序需要执行以下操作：

*   **找到远程对象。** 应用程序可以使用各种机制来获取对远程对象的引用。例如，应用程序可以使用 RMI 的简单命名工具 RMI 注册表注册其远程对象。或者，应用程序可以作为其他远程调用的一部分传递和返回远程对象引用。
*   **与远程对象通信。** 远程对象之间的通信细节由 RMI 处理。对于程序员来说，远程通信看起来类似于常规的 Java 方法调用。
*   **加载传递的对象的类定义。** 因为 RMI 允许对象来回传递，所以它提供了加载对象的类定义以及传输对象数据的机制。

下图描绘了一个 RMI 分布式应用程序，该应用程序使用 RMI 注册表来获取对远程对象的引用。服务器调用注册表以将名称与远程对象关联（或绑定）。客户端在服务器的注册表中按名称查找远程对象，然后在其上调用方法。该图还显示 RMI 系统使用现有的 Web 服务器在需要时从服务器到客户端以及从客户端到服务器加载对象的类定义。

![the RMI system, using an existing web server, communicates from serve to client and from client to server](img/517eb79aa97a7f8fe1d27eab71b4387e.jpg)

RMI 的核心和独特功能之一是，如果未在接收者的 Java 虚拟机中定义类，则可以下载对象类的定义。以前仅在单个 Java 虚拟机中可用的对象的所有类型和行为都可以传输到另一个可能是远程的 Java 虚拟机。 RMI 按实际类传递对象，因此在将对象发送到另一个 Java 虚拟机时，不会更改对象的行为。此功能允许将新类型和行为引入远程 Java 虚拟机，从而动态扩展应用程序的行为。此跟踪中的计算引擎示例使用此功能向分布式程序引入新行为。

与任何其他 Java 应用程序一样，使用 Java RMI 构建的分布式应用程序由接口和类组成。接口声明方法。这些类实现了接口中声明的方法，也许还声明了其他方法。在分布式应用程序中，某些实现可能驻留在某些 Java 虚拟机中，但不存在于其具有可跨 Java 虚拟机调用的方法的对象称为 _ 远程对象 _。

通过实现 _ 远程接口 _，对象变为远程，具有以下特征：

*   远程接口扩展了接口`java.rmi.Remote`。
*   除了任何特定于应用程序的异常之外，接口的每个方法都在其`throws`子句中声明`java.rmi.RemoteException`。

当对象从一个 Java 虚拟机传递到另一个 Java 虚拟机时，RMI 将远程对象与非远程对象区别对待。 RMI 不是在接收 Java 虚拟机中制作实现对象的副本，而是为远程对象传递远程 _ 存根 _。存根充当远程对象的本地代表或代理，并且基本上是客户端的远程引用。客户端调用本地存根上的方法，该方法负责对远程对象执行方法调用。

远程对象的存根实现远程对象实现的同一组远程接口。此属性允许将存根转换为远程对象实现的任何接口。但是，_ 只有 _ 远程接口中定义的那些方法可以从接收 Java 虚拟机中调用。

1.  设计和实现分布式应用程序的组件。
2.  编译来源。
3.  使类网络可访问。
4.  启动应用程序。

### 设计和实现应用程序组件

首先，确定您的应用程序体系结构，包括哪些组件是本地对象以及哪些组件可以远程访问。这一步包括：

*   **定义远程接口。** 远程接口指定客户端可以远程调用的方法。客户端编程到远程接口，而不是这些接口的实现类。这种接口的设计包括确定将用作参数的对象类型以及这些方法的返回值。如果尚不存在任何这些接口或类，则还需要定义它们。
*   **实现远程对象。** 远程对象必须实现一个或多个远程接口。远程对象类可以包括仅在本地可用的其他接口和方法的实现。如果要将任何本地类用于参数或返回任何这些方法的值，则必须同时实现它们。
*   **实现客户。** 在定义远程接口后，包括在部署远程对象之后，可以随时实现使用远程对象的客户端。

### 编译源代码

与任何 Java 程序一样，您使用`javac`编译器来编译源文件。源文件包含远程接口的声明，它们的实现，任何其他服务器类和客户端类。

* * *

**Note:** With versions prior to Java Platform, Standard Edition 5.0, an additional step was required to build stub classes, by using the `rmic` compiler. However, this step is no longer necessary.

* * *

### 使类网络可访问

在此步骤中，您可以访问某些类定义网络，例如远程接口及其关联类型的定义，以及需要下载到客户端或服务器的类的定义。通常可以通过 Web 服务器访问类定义。

### 启动应用程序

启动应用程序包括运行 RMI 远程对象注册表，服务器和客户端。

本节的其余部分将介绍用于创建计算引擎的步骤。

Java 平台的动态特性支持执行任意任务的能力，该平台由 RMI 扩展到网络。 RMI 将任务代码动态加载到计算引擎的 Java 虚拟机中，并在不事先了解实现任务的类的情况下运行任务。这种应用程序具有动态下载代码的能力，通常称为 _ 基于行为的应用程序 _。此类应用程序通常需要完全启用代理程序的基础结构。使用 RMI，此类应用程序是 Java 平台上分布式计算的基本机制的一部分。