定義
Java遠程方法調用,即Java RMI,是分散式應用程式的開發方法之一。用Socket開發分散式應用程式,需要設計一個應用程式級的協定。而RMI則是將客戶和伺服器間的接口抽象為一個本地的過程調用。這樣,我們不需要額外選用或設計協定。
在分散式應用程式中,遠程對象的方法能夠被運行於不同的主機上的其他的Java虛擬機的方法調用。RMI非常類似與其他系統的即C機制,但是比RPC更易用。當所有參數被傳送給遠程的目標並且被解釋,然後將結果返回給調用者時,會給程式設計師一個感覺,以為是從本地類檔案中調用一個本地方法。利用RMI構建分散式套用時利用的Java特徵:透明調用、分散式垃圾回收以及流的方便訪問。
RMI的目標:支持對存在於不同虛擬機上對象的遠程調用、支持伺服器對客戶的回調、把分散式對象模型自然地集成在Java語言裡,儘可能的從語義上保留Java的面向對象的特性、使分散式對象模型和本地Java對象模型間的不同表面化以及使編寫可靠的分散式應用程式儘可能的簡單。
結構
Java RMI系統由以下三層組成:樁/架構(Stub/Skeleton)層,遠程套用和傳輸層。
每一層都山特定的接日和協定來定義,因此,每一層相對於它的相鄰層是獨立的。也就是說,某一層實現上的改變,是不會影響到它的上一層的。例如,在RMI系統中,當前傳輸層是基於TCP的,它可以被基於UDP的傳輸層所替換。通過對象系列化的使用,從一個地址空間傳輸一個對象到另一個地址空間被顯式的完成。樁/架構層是應用程式層與系統其他部分的接口。當開發了一個伺服器應用程式後,就使用RMI的:mic編譯器生成樁/架構層,它根據伺服器程式的位元組代碼,產生代理類。樁/架構層通過抽象編組流,使用對象序列化,傳輸數據到遠程引用層。所以,它並不處理任何特定的傳輸。一個遠程對象客戶端的樁要負責多項任務:初始化遠程調用,序列化傳送參數,提示遠程套用層將進行調用,反序列化返回值或異常,以及提示遠程傳輸層調用完成。另一方面,伺服器端的架構要負責:反序列化客戶端輸入的參數,調用實際的遠程對象實現,以及將返回值或異常序列化成流,以傳輸給客戶。遠程引套用層是樁/架構層和傳輸層的中間層。它負責為獨立於客戶樁和伺服器架構的,多種形式的遠程引用和調用協定提供支持。例如,單點傳送協定可能提供點對點的調用。多點傳送協定可能提供對複製的成組對象的調用。而另外一些協定則可能要處理特定的複製策略或對遠程對象的持久性引用,例如使能遠程對象激活。
傳輸層是一個低級的層,它在不同的地址空間傳輸序列化的流,傳輸層負責建立到遠程地址空間的連線,管理連線,監聽外來調用,維護駐留於同一個地址空間的遠程對象表,為外來的調用建立連線,以及根據遠程調用的目的定位調度程式,並傳遞連線到該調度程式。在這一層,遠程對象引用通過一個對象標識符和一個結束點來表示,它被稱為活動引用。在一個給定的遠程對象的活動引用中,對象標識符指出了遠程調用的對象是什麼,結束點則建立了到遠程對象所駐留的地址空間的連線 。
訪問過程
通過 RMI,一台機器的 Java 對象可以調用在另外一台機器上的遠程對象,就像調用本地對象一樣,這個調用是通過 stub/skeleton 對象作為中轉來進行的,如圖所示。為了實現將服務對象提供給遠程客戶端調用的過程,服務端應該完成以下工作:
1)定義要提供給客戶端訪問的遠程接口,這個接口要求繼承於java.rmi.Remote 接口,而 且這個接口裡面的所有方法都應拋出java.rmi.Remote Exception 異常。同時,由於 RMI 通過將遠程方法的參數和返回值進行序列化後進行傳遞,所以所有遠程接口中的遠程方法的參數和返回值都應該是可以被序列化的,換言之,它們的類型都應該實現了 java.io.Serializable接口。
2)定義遠程接口的實現類。
3)創建遠程接口的對象並且將此對象暴露給客戶端。暴露遠程對象有兩種方式:一種是直接使遠程對象從 java.rmi.server.Unicast Remote Object 類派生出來;另外一種方法是直接調用 java.rmi.server.Unicast Remote Object類的靜態方法。由於第二種方法對遠程對象的要求更少,所以更為常用。為了完成對遠程對象的暴露,還應該對遠程對象在 RMI 註冊表中進行註冊。
優點與不足
RMI 的優點在於:
•遠程調用機制 JDK 本身提供,無需外加其它第三方框架,能夠保持系統的結構簡單。
•遠程調用的數據通訊效率比以 Http 傳輸為基礎的其它遠程調用方案要高。
功能強大,通訊協定可插接。雖然 RMI 是最重要的 Java 遠程調用技術之一,但是仍然有一些不足之處:
•RMI 要求所有的遠程接口必須繼承於 java.rmi.Remote 接口,而且所有遠程接口的方法都應該拋出 java.rmi.Remote Exception 異常,這個要求是否必要,一直存在著較大爭議。一些觀點認為,這種做法給遠程業務對象帶來了不必要的麻煩。而要暴露的對象,只要傳遞的內容可以被序列化,就不應該受到其他更多的限制。
•註冊和暴露遠程對象的過程應該被封裝起來。可以考慮一種機制來將這個過程從編程方式過渡到配置方式,以簡化遠程對象暴露和註冊的過程。
•不利於針對遠程對象的管理和遠程方法的增強以及提供框架性的支持,讓遠程對象管理、對調用的增強、安全驗證的管理等其他重要的方面得到支持。
•RMI 通訊效率還有增加空間。有資料表明,通過重新改進對象的序列化方法,對序列化的算法進行最佳化,可以顯著的提高 RMI 的效率 。