Java 中 RMI 如何使用

发布时间:2021-08-05 17:36:41 作者:Leah
来源:亿速云 阅读:136
# Java 中 RMI 如何使用

## 目录
1. [RMI 概述](#1-rmi-概述)  
2. [RMI 核心组件](#2-rmi-核心组件)  
3. [RMI 开发步骤](#3-rmi-开发步骤)  
   - 3.1 [定义远程接口](#31-定义远程接口)  
   - 3.2 [实现远程接口](#32-实现远程接口)  
   - 3.3 [创建服务端](#33-创建服务端)  
   - 3.4 [创建客户端](#34-创建客户端)  
4. [RMI 运行机制](#4-rmi-运行机制)  
5. [RMI 安全性配置](#5-rmi-安全性配置)  
6. [RMI 高级特性](#6-rmi-高级特性)  
   - 6.1 [动态加载类](#61-动态加载类)  
   - 6.2 [分布式垃圾回收](#62-分布式垃圾回收)  
7. [RMI 常见问题](#7-rmi-常见问题)  
8. [RMI 与替代技术对比](#8-rmi-与替代技术对比)  

---

## 1. RMI 概述

Java RMI(Remote Method Invocation,远程方法调用)是 Java 平台提供的分布式计算解决方案,允许运行在不同 JVM 中的对象通过网络相互调用方法。其核心特点包括:

- **跨JVM通信**:客户端和服务端可部署在不同主机
- **面向对象**:直接调用远程对象的方法,如同本地调用
- **基于序列化**:参数和返回值通过对象序列化传输
- **内置安全机制**:支持安全管理器(SecurityManager)

```java
// 典型RMI调用示例
RemoteObject obj = (RemoteObject)Naming.lookup("rmi://host/service");
obj.method(); // 实际调用发生在远程JVM

2. RMI 核心组件

组件 作用
Remote接口 标记接口,所有远程接口必须继承
RemoteObject 远程对象实现的基类,提供远程语义
UnicastRemoteObject 常用实现类,提供TCP基础的点对点通信
Registry 命名服务,存储远程对象引用(默认端口1099)
Stub & Skeleton 客户端存根和服务端骨架,处理通信细节(Java 5+使用动态代理替代Skeleton)

3. RMI 开发步骤

3.1 定义远程接口

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Calculator extends Remote {
    int add(int a, int b) throws RemoteException;
    double sqrt(double x) throws RemoteException;
}

规范要求: 1. 必须继承java.rmi.Remote 2. 每个方法必须声明throws RemoteException 3. 参数和返回值需实现Serializable

3.2 实现远程接口

import java.rmi.server.UnicastRemoteObject;

public class CalculatorImpl 
    extends UnicastRemoteObject 
    implements Calculator {
    
    public CalculatorImpl() throws RemoteException {
        super(); // 导出远程对象
    }
    
    @Override
    public int add(int a, int b) {
        return a + b;
    }
    
    @Override
    public double sqrt(double x) {
        return Math.sqrt(x);
    }
}

3.3 创建服务端

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Server {
    public static void main(String[] args) {
        try {
            // 创建RMI注册表
            Registry registry = LocateRegistry.createRegistry(1099);
            
            // 绑定服务
            Calculator service = new CalculatorImpl();
            registry.rebind("CalculatorService", service);
            
            System.out.println("Server ready...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.4 创建客户端

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Client {
    public static void main(String[] args) {
        try {
            // 获取远程注册表
            Registry registry = LocateRegistry.getRegistry("localhost", 1099);
            
            // 查找远程对象
            Calculator calculator = (Calculator) registry.lookup("CalculatorService");
            
            // 调用远程方法
            System.out.println("3 + 5 = " + calculator.add(3, 5));
            System.out.println("√16 = " + calculator.sqrt(16));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4. RMI 运行机制

  1. 注册阶段

    • 服务端导出远程对象生成Stub
    • Stub注册到Registry
  2. 调用阶段

    sequenceDiagram
    Client->>Stub: 调用方法
    Stub->>Skeleton: 序列化参数并传输
    Skeleton->>ServiceImpl: 反序列化并调用实际方法
    ServiceImpl->>Skeleton: 返回结果
    Skeleton->>Stub: 序列化结果
    Stub->>Client: 返回反序列化后的结果
    
  3. 通信协议

    • 默认使用JRMP(Java Remote Method Protocol)
    • 可扩展支持IIOP(通过RMI-IIOP)

5. RMI 安全性配置

安全策略文件(server.policy)

grant {
    permission java.net.SocketPermission "*:1024-65535", "connect,accept";
    permission java.net.SocketPermission "*:1099", "listen";
};

启动服务端时加载策略

java -Djava.rmi.server.codebase=http://yourserver.com/classes/
    -Djava.security.policy=server.policy
    Server

关键安全措施: 1. 限制codebase来源 2. 控制Socket权限 3. 使用SSL加密通信(需配置javax.net.ssl属性)


6. RMI 高级特性

6.1 动态加载类

// 服务端启动参数
-Djava.rmi.server.codebase=http://myserver/rmi_classes/

// 客户端自动从指定URL下载缺失类

6.2 分布式垃圾回收(DGC)


7. RMI 常见问题

问题1:Connection refused - 检查Registry是否启动 - 验证防火墙设置

问题2:ClassNotFoundException - 确保codebase配置正确 - 客户端包含所需接口类

问题3:性能瓶颈 - 优化序列化(实现Externalizable) - 使用连接池复用Stub


8. RMI 与替代技术对比

特性 RMI WebService gRPC
协议 JRMP/IIOP HTTP/SOAP HTTP/2
数据格式 Java序列化 XML/JSON Protobuf
跨语言 仅Java 支持 支持
性能 较低 极高
适用场景 Java系统内部通信 异构系统集成 微服务间通信

最佳实践建议: 1. 优先考虑接口设计,避免频繁修改远程接口 2. 对于大量数据传输,考虑使用RemoteInputStream等模式 3. 生产环境建议结合Spring框架简化开发 4. 监控DGC活动防止内存泄漏 “`

注:本文实际约3000字,完整5000字版本可扩展以下内容: 1. 完整代码示例(含异常处理) 2. Spring整合RMI的详细方案 3. 性能调优具体参数 4. 与JMS的详细对比 5. 分布式事务处理方案 6. 实际项目案例剖析

推荐阅读:
  1. Java RMI是什么
  2. JAVA中的RPC框架有哪些

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java rmi

上一篇:Python中Selenium如何使用

下一篇:如何解决某些HTML字符打不出来的问题

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》