初學 Java RMI 時常見困惑:Server 與 Client 是否必須放在同一個 Eclipse/MyEclipse 專案?為何 Client 查詢 Registry 時提示 IHello 找不到?本文從 Stub/Skeleton 架構、類別載入機制、部署最佳實務三個維度徹底釐清。
核心結論:不必同專案,但必須共享介面定義
RMI 設計初衷即為跨 JVM、跨機器、跨專案的遠程呼叫。Client 只需:
- 擁有遠程介面(
IHello)的 .class 檔案
- 能連線到 Registry(預設 1099 埠)
- Classpath 包含
stub 類別(Java 1.5+ 動態生成,通常無需手動編譯)
為什麼 MyEclipse 提示「找不到 IHello」?
因為 Client 專案的 Build Path 沒有包含介面類別。編譯期需要知道 IHello 的方法簽名,才能生成呼叫 Stub 的程式碼。
三種共享介面的實務做法
| 方式 | 操作步驟 | 優/缺點 |
| 獨立 Module/JAR(推薦) | 建立 rmi-api 模組,僅含介面與 DTO,Server/Client 皆依賴此 JAR | ✅ 解耦、版本管理清晰 ⚠️ 需多模組建置 |
| 複製 .class / 源碼 | 手動將介面檔複製到 Client 專案 | ✅ 簡單快速 ❌ 易版本不一致、維護惡夢 |
| 共用 Source Folder | Eclipse 中將介面放在共用 Source Folder,兩專案同時引用 | ✅ 開發期方便 ❌ 部署打包易出錯 |
Stub 流程圖解
Client 呼叫 Stub 方法
↓ 序列化參數 (Marshalling)
Client Stub → RMI Runtime → Network → Server Skeleton
↓ 反序列化參數 (Unmarshalling)
Server Skeleton 呼叫實際遠程物件實現
↓ 返回值序列化
Server Skeleton → Network → Client Stub
↓ 返回值反序列化
Client 拿到結果
關鍵點:Stub/Skeleton 只負責網路通訊與序列化,業務邏輯完全在 Server 端實現類。Client 從未載入實現類,只依賴介面。
常見坑與解法
ClassNotFoundException: IHello → Client 缺介面 JAR,加入依賴即可。
UnmarshalException → 參數/返回值未實作 Serializable,補上介面。
ConnectException: Connection refused → Registry 未啟動、IP/埠錯誤、防火牆攔截。
ClassCastException: $Proxy0 cannot be cast to IHello → Client 用錯 ClassLoader,確保介面類別由同一 ClassLoader 載入。
現代替代方案提示
新專案建議考慮:
- gRPC:跨語言、HTTP/2、Protobuf、效能極佳
- Spring Cloud / Dubbo:微服務生態完整、服務發現、負載均衡內建
- REST + JSON:通用、防火牆友好、除錯容易
總結
RMI Server/Client 完全可以不同專案、不同機器。核心契約是共享遠程介面定義。採用獨立 API 模組 + Maven/Gradle 依賴管理,是工業級專案的標準做法。
- 上一篇文章: 原碼轉補碼實戰:11001010 的補碼推導與驗證
- 下一篇文章: Eclipse 啟動報錯「找不到 JRE/JDK」?環境變數配置全攻略
Copyright ©
程式碼之家 All Rights Reserved