RMI(远程方法调用)是一种 API,它提供了一种在 java 中创建分布式应用程序的机制。 RMI 允许对象调用在另一个 JVM 中运行的对象的方法。
RMI 使用两个对象存根(桩)和框架在应用程序之间提供远程通信。
RMI 使用存根和骨架对象与远程对象进行通信。
远程对象是可以从另一个 JVM 调用其方法的对象。让我们了解存根和骨架对象:
存根是一个对象,充当客户端的网关。所有传出请求都通过它进行路由。它驻留在客户端并代表远程对象。当调用者调用存根对象上的方法时,它会执行以下任务:
骨架是一个对象,充当服务器端对象的网关。所有传入的请求都通过它进行路由。当骨架接收到传入的请求时,它会执行以下任务:
在 Java 2 SDK 中,引入了一个存根协议,消除了对骨架的需求。

如果任何应用程序执行这些任务,它就可以是分布式应用程序。
RMI 应用程序具有所有这些特性,因此称为分布式应用程序。
给出了编写 RMI 程序的 6 个步骤。
在这个例子中,我们按照所有 6 个步骤来创建和运行 rmi 应用程序。客户端应用程序只需要两个文件,远程接口和客户端应用程序。在 rmi 应用程序中,客户端和服务器都与远程接口交互。客户端应用程序调用代理对象上的方法,RMI 将请求发送到远程 JVM。返回值被发送回代理对象,然后发送到客户端应用程序。

1)创建远程接口
要创建远程接口,请扩展 Remote 接口并使用远程接口的所有方法声明 RemoteException。在这里,我们正在创建一个扩展远程接口的远程接口。只有一个名为 add() 的方法,它声明 RemoteException。
- import java.rmi.*;
- public interface Adder extends Remote{
- public int add(int x,int y)throws RemoteException;
- }
2)提供远程接口的实现
现在提供远程接口的实现。为了提供 Remote 接口的实现,我们需要:
如果您扩展 UnicastRemoteObject 类,则必须定义一个声明 RemoteException 的构造函数。
- import java.rmi.*;
- import java.rmi.server.*;
- public class AdderRemote extends UnicastRemoteObject implements Adder{
- AdderRemote()throws RemoteException{
- super();
- }
- public int add(int x,int y){return x+y;}
- }
3) 使用 rmic 工具创建存根和骨架对象。
下一步是使用 rmi 编译器创建存根和骨架对象。 rmic 工具调用 RMI 编译器并创建存根和骨架对象。
rmic AdderRemote
4)通过rmiregistry工具启动registry服务
现在使用 rmiregistry 工具启动注册表服务。如果您不指定端口号,它将使用默认端口号。在此示例中,我们使用端口号 5000。
rmiregistry 5000
5) 创建并运行服务器应用程序
现在 rmi 服务需要托管在服务器进程中。 Naming 类提供了获取和存储远程对象的方法。 Naming 类提供了 5 种方法。如下表所列:
| public static java.rmi.Remote lookup(java.lang.String) throws java.rmi.NotBoundException, java.net.MalformedURLException, java.rmi.RemoteException; | It returns the reference of the remote object. |
| public static void bind(java.lang.String, java.rmi.Remote) throws java.rmi.AlreadyBoundException, java.net.MalformedURLException, java.rmi.RemoteException; | It binds the remote object with the given name. |
| public static void unbind(java.lang.String) throws java.rmi.RemoteException, java.rmi.NotBoundException, java.net.MalformedURLException; | It destroys the remote object which is bound with the given name. |
| public static void rebind(java.lang.String, java.rmi.Remote) throws java.rmi.RemoteException, java.net.MalformedURLException; | It binds the remote object to the new name. |
| public static java.lang.String[] list(java.lang.String) throws java.rmi.RemoteException, java.net.MalformedURLException; | It returns an array of the names of the remote objects bound in the registry. |
在此示例中,我们通过名称 sonoo 绑定远程对象。
- import java.rmi.*;
- import java.rmi.registry.*;
- public class MyServer{
- public static void main(String args[]){
- try{
- Adder stub=new AdderRemote();
- Naming.rebind("rmi://localhost:5000/sonoo",stub);
- }catch(Exception e){System.out.println(e);}
- }
- }
6) 创建并运行客户端应用程序
在客户端,我们通过 Naming 类的 lookup() 方法获取存根对象,并在该对象上调用该方法。在此示例中,我们在同一台机器上运行服务器和客户端应用程序,因此我们使用 localhost。如果要从另一台机器访问远程对象,请将 localhost 更改为远程对象所在的主机名(或 IP 地址)。
- import java.rmi.*;
- public class MyClient{
- public static void main(String args[]){
- try{
- Adder stub=(Adder)Naming.lookup("rmi://localhost:5000/sonoo");
- System.out.println(stub.add(34,4));
- }catch(Exception e){}
- }
- }
- For running this rmi example,
-
- 1) compile all the java files
-
- javac *.java
-
- 2)create stub and skeleton object by rmic tool
-
- rmic AdderRemote
-
- 3)start rmi registry in one command prompt
-
- rmiregistry 5000
-
- 4)start the server in another command prompt
-
- java MyServer
-
- 5)start the client application in another command prompt
-
- java MyClient
