一、RMI系統運行機理
RMI應用程序通常包括兩個(gè)獨立的程序:服務(wù)器程序和客戶(hù)機程序。典型的服務(wù)器應用程序將創(chuàng )建多個(gè)遠程對象,使這些遠程對象能夠被引用,然后等待客戶(hù)機調用這些遠程對象的方法。而典型的客戶(hù)機程序則從服務(wù)器中得到一個(gè)或多個(gè)遠程對象的引用,然后調用遠程對象的方法。RMI為服務(wù)器和客戶(hù)機進(jìn)行通信和信息傳遞提供了一種機制。
在與遠程對象的通信過(guò)程中,RMI使用標準機制:stub和skeleton。遠程對象的stub擔當遠程對象的客戶(hù)本地代表或代理人角色。調用程序將調用本地stub的方法,而本地stub將負責執行對遠程對象的方法調用。在RMI中,遠程對象的stub與該遠程對象所實(shí)現的遠程接口集相同。調用stub的方法時(shí)將執行下列操作:(1) 初始化與包含遠程對象的遠程虛擬機的連接;(2) 對遠程虛擬機的參數進(jìn)行編組(寫(xiě)入并傳輸);(3) 等待方法調用結果;(4) 解編(讀?。┓祷刂祷蚍祷氐漠惓?;(5) 將值返回給調用程序。為了向調用程序展示比較簡(jiǎn)單的調用機制,stub將參數的序列化和網(wǎng)絡(luò )級通信等細節隱藏了起來(lái)。在遠程虛擬機中,每個(gè)遠程對象都可以有相應的skeleton(在JDK1.2環(huán)境中無(wú)需使用skeleton)。Skeleton負責將調用分配給實(shí)際的遠程對象實(shí)現。它在接收方法調用時(shí)執行下列操作:(1) 解編(讀?。┻h程方法的參數;(2) 調用實(shí)際遠程對象實(shí)現上的方法;(3) 將結果(返回值或異常)編組(寫(xiě)入并傳輸)給調用程序。stub和skeleton由rmic編譯器生成。
利用RMI編寫(xiě)分布式對象應用程序需要完成以下工作:(1) 定位遠程對象。應用程序可使用兩種機制中的一種得到對遠程對象的引用。它既可用RMI的簡(jiǎn)單命名工具rmiregistry來(lái)注冊它的遠程對象,也可以將遠程對象引用作為常規操作的一部分來(lái)進(jìn)行傳遞和返回。(2)與遠程對象通信。遠程對象間通信的細節由RMI處理,對于程序員來(lái)說(shuō),遠程通信看起來(lái)就像標準的Java方法調用。(3)給作為參數或返回值傳遞的對象加載類(lèi)字節碼。因為RMI允許調用程序將純Java對象傳給遠程對象,所以,RMI將提供必要的機制,既可以加載對象的代碼又可以傳輸對象的數據。在RMI分布式應用程序運行時(shí),服務(wù)器調用注冊服務(wù)程序以使名字與遠程對象相關(guān)聯(lián)??蛻?hù)機在服務(wù)器上的注冊服務(wù)程序中用遠程對象的名字查找該遠程對象,然后調用它的方法。
二、對象序列化
在RMI分布式應用系統中,服務(wù)器與客戶(hù)機之間傳遞的Java對象必須是可序列化的對象。不可序列化的對象不能在對象流中進(jìn)行傳遞。對象序列化擴展了核心Java輸入/輸出類(lèi),同時(shí)也支持對象。對象序列化支持把對象編碼以及將通過(guò)它們可訪(fǎng)問(wèn)到的對象編碼變成字節流;同時(shí),它也支持流中對象圖形的互補重構造。序列化用于輕型持久性和借助于套接字或遠程方法調用(RMI)進(jìn)行的通信。序列化中現在包括一個(gè) API(Application Programming Interface,應用程序接口),允許獨立于類(lèi)的域指定對象的序列化數據,并允許使用現有協(xié)議將序列化數據域寫(xiě)入流中或從流中讀取,以確保與缺省讀寫(xiě)機制的兼容性。
為編寫(xiě)應用程序,除多數瞬態(tài)應用程序外,都必須具備存儲和檢索 Java對象的能力。以序列化方式存儲和檢索對象的關(guān)鍵在于提供重新構造該對象所需的足夠對象狀態(tài)。存儲到流的對象可能會(huì )支持 Serializable(可序列化)或 Externalizable(可外部化)接口。對于Java對象,序列化形式必須能標識和校驗存儲其內容的對象所屬的 Java類(lèi),并且將該內容還原為新的實(shí)例。對于可序列化對象,流將提供足夠的信息將流的域還原為類(lèi)的兼容版本。對于可外部化對象,類(lèi)將全權負責其內容的外部格式。序列化 Java 對象的目的是:提供一種簡(jiǎn)單但可擴充的機制,以序列化方式維護 Java對象的類(lèi)型及安全屬性;具有支持編組和解編的擴展能力以滿(mǎn)足遠程對象的需要;具有可擴展性以支持 Java 對象的簡(jiǎn)單持久性;只有在自定義時(shí),才需對每個(gè)類(lèi)提供序列化自實(shí)現;允許對象定義其外部格式。
三、分布式應用的實(shí)現和運行步驟
編寫(xiě)Java RMI分布式應用程序的步驟主要包括以下幾步:
(1) 將遠程類(lèi)的功能定義為Java接口。在Java中,遠程對象是實(shí)現遠程接口的類(lèi)的實(shí)例。在遠程接口中聲明每個(gè)要遠程調用的方法。遠程接口具有如下特點(diǎn):1) 遠程接口必須聲明為public。如果不這樣,則除非客戶(hù)端與遠程接口在同一個(gè)包內,否則當試圖裝入實(shí)現該遠程接口的遠程對象時(shí)會(huì )得到錯誤結果。2) 遠程對象擴展java.rmi.Remote接口。3) 除了所有應用程序特定的例外之外,每個(gè)方法還必須拋出java.rmi.RemoteException例外。4) 任何作為參數或返回值傳送的遠程對象的數據類(lèi)型必須聲明為遠程接口類(lèi)型,而不是實(shí)現類(lèi)。
(2) 編寫(xiě)和實(shí)現服務(wù)器類(lèi)。該類(lèi)是實(shí)現(1)中定義的遠程接口。所以在該類(lèi)中至少要聲明實(shí)現一個(gè)遠程接口,并且必須具有構造方法。在該類(lèi)中還要實(shí)現遠程接口中所聲明的各個(gè)遠程方法。
(3) 編寫(xiě)使用遠程服務(wù)的客戶(hù)機程序。在該類(lèi)中使用java.rmi.Naming中的lookup()方法獲得對遠程對象的引用,依據需要調用該引用的遠程方法,其調用方式和對本地對象方法的調用相同。
實(shí)現了服務(wù)器和客戶(hù)機的程序后,就是編譯和運行該RMI系統。其步驟有:
(1) 使用javac編譯遠程接口類(lèi),遠程接口實(shí)現類(lèi)和客戶(hù)機程序。
(2) 使用rmic編譯器生成實(shí)現類(lèi)的stub和skeleton。
(3) 啟動(dòng)RMI注冊服務(wù)程序rmiregistry。
(4) 啟動(dòng)服務(wù)器端程序。
(5) 啟動(dòng)客戶(hù)機程序。
聯(lián)系客服