Java RMI (Remote Method Invocation) 與 CORBA (Common Object Request Broker Architecture) 是分散式物件系統的兩大支柱。本文不僅對比兩者架構特性,更以完整的「遠端檔案下載系統」為例,手把手帶你實作 RMI 分散式應用的完整生命週期。
雙方協定共同通訊協定(如 HTTP GET),透過 Socket 交換訊息。缺點:協定設計複雜、緊耦合、擴充性差。
核心概念:以明確定義的介面隔離服務請求端(Client)與提供端(Server)。Client 僅持有介面參考,呼叫遠端方法如同呼叫本地方法,實作細節完全封裝。RMI 與 CORBA 皆屬此模型。
extends Remote)extends UnicastRemoteObject)import java.rmi.Remote;
import java.rmi.RemoteException;
public interface FileInterface extends Remote {
// 遠端方法:接收檔名,回傳位元組陣列
public byte[] downloadFile(String fileName) throws RemoteException;
}
三大鐵律:public 介面、extends Remote、所有方法 throws RemoteException
import java.io.*;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
public class FileImpl extends UnicastRemoteObject implements FileInterface {
private String name;
public FileImpl(String s) throws RemoteException {
super(); // 啟動 RMI 連結
name = s;
}
public byte[] downloadFile(String fileName) {
try {
File file = new File(fileName);
byte[] buffer = new byte[(int) file.length()];
try (BufferedInputStream input = new BufferedInputStream(
new FileInputStream(fileName))) {
input.read(buffer, 0, buffer.length);
}
return buffer;
} catch (Exception e) {
System.out.println("FileImpl: " + e.getMessage());
e.printStackTrace();
return null;
}
}
}
關鍵點:繼承 UnicastRemoteObject 表示單一、不可複寫的遠端物件,使用預設 TCP 通道。
import java.rmi.*;
public class FileServer {
public static void main(String[] args) {
// 安裝安全管理員(RMI 必須)
if (System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
try {
FileInterface fi = new FileImpl("FileServer");
// 註冊到 RMI Registry (預設 port 1099)
Naming.rebind("//127.0.0.1/FileServer", fi);
System.out.println("FileServer ready...");
} catch (Exception e) {
System.out.println("FileServer: " + e.getMessage());
e.printStackTrace();
}
}
}
進階配置:若 Registry 非預設埠,使用 //host:port/name 格式;跨機器部署時修改 IP 位址即可。
import java.io.*;
import java.rmi.*;
public class FileClient {
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("Usage: java FileClient fileName machineName");
System.exit(0);
}
try {
String name = "//" + args[1] + "/FileServer";
FileInterface fi = (FileInterface) Naming.lookup(name);
byte[] fileData = fi.downloadFile(args[0]);
// 儲存到本地
try (BufferedOutputStream out = new BufferedOutputStream(
new FileOutputStream(new File(args[0]).getName()))) {
out.write(fileData, 0, fileData.length);
out.flush();
}
System.out.println("Download complete: " + args[0]);
} catch (Exception e) {
System.err.println("FileClient exception: " + e.getMessage());
e.printStackTrace();
}
}
}
javac *.java
rmic FileImpl # 產生 FileImpl_Stub.class, FileImpl_Skel.class
# Windows
start rmiregistry
# 或指定埠
rmiregistry 4500
grant {
permission java.security.AllPermission "", "";
};
警告:生產環境必須制定嚴格權限策略,絕不可使用 AllPermission。
java -Djava.security.policy=policy.txt FileServer
java FileClient test.txt 192.168.1.100
避免手動複製介面/Stub 類別,啟動 HTTP 伺服器托管類別檔案:
# Server 端啟動參數
java -Djava.rmi.server.codebase=https://serverhost/classes/ FileServer
# Client 端自動從 codebase 下載所需類別
java -Djava.rmi.server.codebase=https://serverhost/classes/ FileClient ...
| 維度 | RMI | CORBA |
|---|---|---|
| 語言綁定 | 純 Java | 多語言 (IDL 映射) |
| 介面定義 | Java 介面 | IDL |
| 物件傳遞 | 序列化 (Pass-by-value) | VALUETYPE / 遠端參考 |
| 防火牆穿透 | 困難 (隨機埠) | IIOP 固定埠較易 |
| 效能 | Java 環境極佳 | 跨語言有序列化開銷 |
| 成熟度 | Java 生態整合度高 | 企業級異構系統標準 |
RMI 以其簡潔的 Java 原生特性,成為 Java 分散式開發的首選。本文檔案下載範例完整展示了「介面定義 → 實作 → 註冊 → 查找 → 呼叫」的標準流程。掌握安全策略、Stub 產生、動態類別載入等關鍵環節,即可構建健壯的分散式 Java 系統。對於異構語言整合需求,CORBA/IIOP 則提供標準化解決方案。