RMI 概述
什么是 RMI?
远程方法调用(Remote Method Invocation,RMI)是 Java 提供的一种用于实现分布式计算的 API。它允许在不同 Java 虚拟机上的对象进行远程方法调用,就像调用本地方法一样简单。
RMI 的核心特点
- 透明性:远程调用对开发者来说几乎和本地调用一样
 - 类型安全:基于 Java 的强类型系统
 - 面向对象:直接操作对象和方法
 - 安全性:利用 Java 安全机制
 
RMI 架构
基本组件
- Registry(注册中心)
    
- 管理远程对象
 - 提供服务发现机制
 
 - Remote Interface(远程接口)
    
- 定义可远程调用的方法
 - 必须继承 
java.rmi.Remote 
 - Remote Object(远程对象)
    
- 实现远程接口
 - 提供具体的方法实现
 
 
通信流程
客户端 -> 注册中心 -> 远程对象 -> 执行 -> 返回结果
实战示例
1. 定义远程接口
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface CalculatorService extends Remote {
    int add(int a, int b) throws RemoteException;
    int subtract(int a, int b) throws RemoteException;
}
2. 实现远程接口
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class CalculatorServiceImpl extends UnicastRemoteObject implements CalculatorService {
    protected CalculatorServiceImpl() throws RemoteException {
        super();
    }
    @Override
    public int add(int a, int b) throws RemoteException {
        return a + b;
    }
    @Override
    public int subtract(int a, int b) throws RemoteException {
        return a - b;
    }
}
3. 服务端代码
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIServer {
    public static void main(String[] args) {
        try {
            // 创建远程对象
            CalculatorService service = new CalculatorServiceImpl();
            
            // 创建注册中心
            Registry registry = LocateRegistry.createRegistry(1099);
            
            // 绑定远程对象
            registry.rebind("CalculatorService", service);
            
            System.out.println("RMI Server is running...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
4. 客户端代码
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RMIClient {
    public static void main(String[] args) {
        try {
            // 获取注册中心
            Registry registry = LocateRegistry.getRegistry("localhost", 1099);
            
            // 查找远程对象
            CalculatorService service = (CalculatorService) registry.lookup("CalculatorService");
            
            // 调用远程方法
            int result1 = service.add(10, 20);
            int result2 = service.subtract(30, 15);
            
            System.out.println("Add result: " + result1);
            System.out.println("Subtract result: " + result2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
高级特性
1. 安全性
// 设置 RMI 安全管理器
System.setSecurityManager(new RMISecurityManager());
2. 动态类加载
RMI 支持动态类加载,允许客户端下载服务端的类定义。
3. 异常处理
try {
    // RMI 调用
} catch (RemoteException e) {
    // 处理网络和远程调用异常
}
性能优化
- 连接池:重用 RMI 连接
 - 缓存:缓存远程调用结果
 - 批量调用:减少网络开销
 
替代方案
- WebService
 - gRPC
 - Apache Thrift
 - Spring Remoting
 
最佳实践
- 保持接口简单
 - 处理所有可能的异常
 - 使用安全管理器
 - 考虑性能开销
 - 实现适当的超时机制
 
常见问题
1. 端口占用
- 默认端口:1099
 - 可通过 
LocateRegistry.createRegistry(port)自定义 
2. 网络防火墙
- 需要开放特定端口
 - 配置安全组规则
 
总结
Java RMI 提供了一种简单、类型安全的远程方法调用机制。尽管现代微服务架构更倾向于使用 gRPC 或 RESTful 服务,但 RMI 在特定场景下仍然是一个强大的分布式通信解决方案。
掌握 RMI 不仅能帮助你理解分布式系统的基本原理,还能为更复杂的分布式架构奠定基础。