RMI-IIOP (Remote Method Invocation over Internet Inter-ORB Protocol) 融合了 **Java RMI 易用性** 與 **CORBA 互操作性**,是 J2EE 容器間通信、EJB 遠程調用的標準協議棧。
java.rmi.Remote 標記介面public interface Remote { } // 無方法,純標記
強制規則:
Remote (直接或間接)throws 中聲明 RemoteException (或其父類 IOException, Exception)| 類型 | 傳遞方式 | 序列化要求 | 遠程修改可見性 |
|---|---|---|---|
| 基本類型 | 按值 (複製) | 無 | 不可見 |
可序列化對象 (Serializable) | 按值 (深拷貝) | 實現 Serializable,建議显式 serialVersionUID | 不可見 (各持副本) |
遠程對象 (Remote) | 按引用 (傳遞 Stub) | 無需序列化,Stub 可序列化 | 可見 (操作同一遠程實例) |
外部化對象 (Externalizable) | 按值 (自定義格式) | 實現 writeExternal/readExternal | 不可見 |
單次遠程調用中,同一對象的多個引用 (參數圖中) 在遠端將映射為 **同一 Stub 實例**,保持對象圖拓撲結構不變。
annotateClass 機制codebase URL (HTTP/FTP/file)SocketPermission、FilePermission)Context:命名上下文,提供 bind/rebind/unbind/lookup/list 操作Name:複合名稱 (如 java:comp/env/jdbc/MyDS),支援複合命名規則InitialContext:進入點,根據環境屬性 (java.naming.factory.initial, provider.url) 連接具體命名服務| 子上下文 | 用途 | 示例 |
|---|---|---|
java:comp/env | 組件環境項目 (ENC) | jdbc/MyDS, ejb/MyBean, jms/MyQueue |
java:global | 應用級全域綁定 (EJB 3.1+) | java:global/app/module/BeanName!Interface |
java:app | 模組級共享綁定 | java:app/module/BeanName |
java:module | 當前模組綁定 | java:module/BeanName |
<!-- EJB 2.x: Home 介面查找 -->
Context ctx = new InitialContext();
Object ref = ctx.lookup("java:comp/env/ejb/MyBean");
MyHome home = (MyHome) PortableRemoteObject.narrow(ref, MyHome.class);
MyRemote remote = home.create();
// EJB 3.x: 無 Home 介面,直接查找業務介面 (可攜帶全域 JNDI 名)
@EJB // 依賴注入 (容器管理環境)
MyBusinessInterface ejb;
// 或 程式化查找
Context ctx = new InitialContext();
MyBusinessInterface ejb = (MyBusinessInterface) ctx.lookup("java:global/myApp/myModule/MyBean!com.demo.MyBusinessInterface");
InitialContext (配置 Provider URL 指向目標服務器)lookup(jndiName) 返回 Stub 序列化形式,經反序列化還原為本地 Stub| 異常 | 典型原因 | 排查方向 |
|---|---|---|
ClassNotFoundException: Stub | 客戶端缺少 Stub 類、codebase 未配置/不可達 | 檢查 java.rmi.server.codebase、HTTP 類服務器、防火牆 |
NoSuchObjectException | 遠程對象已失效、容器重啟、租約過期 | 檢查 EJB 生命週期、@Remove 調用、容器閒置超時配置 |
MarshalException | 參數/返回值不可序列化、serialVersionUID 不匹配 | 實現 Serializable、显式 serialVersionUID、檢查傳遞對象圖 |
CommunicationException | 網絡不通、防火牆攔截 IIOP 端口 (默認 3700/3500)、ORB 端點配置錯誤 | Telnet 端口、檢查 ORBListenPort、ORBInitialHost |
NamingException | JNDI 名稱錯誤、Provider URL 錯誤、命名服務未啟動 | 驗證 java.naming.provider.url、list() 瀏覽命名樹 |
遷移策略:**Strangler Fig 模式** —— 新服務採用現代協議,舊 EJB 通過適配器/網關暴露為 REST/gRPC,逐步剝離 RMI-IIOP 依賴。
RMI-IIOP 與 JNDI 共同構建了 J2EE 時代分布式計算的「網絡層」與「地址簿」。理解其 **Stub/Skeleton 代理機制、參數傳遞語義、動態類加載、命名上下文層級、遠程引用生命週期**,不僅是維護遺產系統的必備技能,更是掌握現代微服務通信本質 (服務發現、負載均衡、序列化、超時重試、熔斷) 的認知基石。技術棧更迭,分布式核心難題永恆不變。