程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2EE >> RMI規范--七

RMI規范--七

編輯:J2EE
第 7 章 主題: 概述 激活協議 “可激活”遠程對象的實現模型 激活接口 .1 概述 分布式對象系統被設計為支持長期存在的持久對象。假設這些系統將由成千(也 許成萬)個這樣的對象組成,則對象的實現在無限期的時間段內被激活並保持活 動狀態是不合理的。這將占用寶貴的系統資源。另外,客戶機需要保存對對象的 持久引用的能力,這樣在一個系統崩潰後可以重新建立對象之間的通訊,因為通 常對一個分布對象的引用只有當對象處於活動狀態時才有效。 對象激活是一種用來提供對對象持久引用和管理對象實現的執行的機制。在 RMI 中,激活允許對象根據需要開始執行。當訪問(通過方法調用)“可激活”遠程 對象時,如果該遠程對象當前尚未執行,則系統將在適當的 Java 虛擬機中開始 該對象的執行。 7.1.1 術語 活動 (active) 對象是在某些系統的 Java 虛擬機中被實例化並被導出的遠程對 象。非活動對象在虛擬機中尚未被實例化(或導出),但能變成活動狀態的遠程 對象。激活就是將非活動對象轉化為活動對象的過程。激活要求對象與一台虛擬 機相關聯,而這將可能需要將該對象的類加載到虛擬機中,同時該對象也恢復其 持久狀態(如果有)。 在 RMI 系統中,我們使用了惰性激活。惰性激活就是將一個對象的激活延遲到客 戶機第一次使用該對象時(即第一次方法調用時)。 7.1.2 惰性激活 遠程對象的惰性激活是用不完善遠程引用(有時稱為不完善塊)實現的。對遠程 對象的不完善遠程引用在第一次調用對象的方法時,“完善”為活動對象的引用 。每個不完善引用均保持一個持久句柄(激活標識符)和對目標遠程對象的瞬態 遠程引用。遠程對象的激活標識符包含足夠的信息來使第三方激活該對象。瞬態 引用是對可用來聯系執行對象的主動遠程對象的“活動”引用。 在不完善引用中,如果對遠程對象的活引用為空,則不認為目標對象是主動的。 在方法調用中,不完善引用(對該對象)將加入激活協議以獲得“活”引用,該 引用是對新激活的對象的遠程引用(例如單路傳送 (unicast) 的遠程引用)。一 旦不完善引用得到活引用,則不完善引用將把方法調用傳給底層的遠程引用,而 該遠程引用又將方法調用傳給遠程對象。 具體的說,遠程對象的 stub 包含一個“不完善”遠程引用類型,該類型既包括: 遠程對象的激活標識符,又包括 “活”引用(可能為空),其中包含遠程對象的“活動”遠程引用類型(例如, 帶有單路傳送語義的遠程引用類型)。 ---------------------------------------------------------------------- ---------- 注意 - RMI 系統對遠程調用保留“至多一次”語義。換句話說,對可激活或單路 傳送遠程對象的調用將至多發送一次。因此,如果對遠程對象的調用失敗(由拋 出的 RemoteException 異常表示),則客戶機將得到如下保證:遠程方法的執行 不會超過一次,甚至根本就不執行。 7.2 激活協議 在遠程方法調用期間,如果目標對象的“活”(live) 引用是未知的,則不完善引 用將使用激活協議。激活協議包括下列幾個實體:不完善引用、激活器、Java 虛 擬機中的激活組和被激活的遠程對象。 激活器(通常每個主機有一個)是一個實體,負責激活,它是: 將激活標識符映射到激活對象所需信息(對象的類、位置 -- URL 路徑 -- 從該 處可加載類、對象可能需要用於自舉 (bootstrap) 的特定數據等)的信息數據庫,及 Java 虛擬機的管理器,它啟動虛擬機(必要時)並將對象激活請求(和必要的信 息一起)傳送到遠程虛擬機中正確的激活組。 注意:激活器始終將激活標識符到活動對象的當前映射保存在緩存中,這樣就無 需為每個激活請求而查詢該組。 激活組(每個 Java 虛擬機中一個)是這樣的實體,它接收對激活 Java 虛擬機 中對象的請求並將激活的對象返給激活器。 激活協議如下所示。不完善引用使用一個激活標識符並調用激活器(內部 RMI 接 口)來激活與該標識符關聯的對象。激活器查找對象的激活描述符(先前已注冊 )。對象的描述符包括: 對象的組標識符(指定對象激活時所處的虛擬機), 對象的類名, URL 路徑,從該處加載對象的類代碼, 特定於對象的已編組的初始化數據(例如,初始化數據可能是包含對象持久狀態 的文件的名稱)。 如果應容納該對象的激活組存在,則激活器將激活請求傳送到該組。如果激活組 不存在,則激活器將啟動虛擬機以執行激活組,然後將激活請求傳送到該組。 激活組將加載對象的類並用特定的構造函數來實例化該對象。此構造函數帶多個 參數,包括先前注冊的激活描述符。 對象完成激活時,激活組將把已編組對象引用傳回激活器,然後該激活器記錄激 活標識符和激活引用對,並將活動(活)引用返給不完善引用。隨後,不完善引 用(在 stub 內)通過活動引用將方法調用直接傳給遠程對象。 ---------------------------------------------------------------------- ---------- 注意 - 在 JDK 中,RMI 提供激活系統接口的實現。要使用激活,必須首先運行 激活系統守護進程 (daemon) rmid。 7.3 “可激活”遠程對象的實現模型 為了使可通過激活標識符訪問的遠程對象不受時間影響,開發人員必須做到: 為該遠程對象注冊一個激活描述符 在對象的類中包含一個專用構造函數,當 RMI 系統激活可激活對象時將調用它。 可用以下幾種方法來注冊激活描述符 (ActivationDesc): 調用類 Activatable 的靜態 register 方法 用 Activatable 類的第一個或第二個構造函數創建“可激活”對象 顯式地導出“可激活”對象。該過程可用 Activatable 的第一個或第二個 expo rtObject 方法實現,其參數為 ActivationDesc、Remote 對象的實現和端口號。 對於特定對象,只可用上述三種方法之一來注冊激活對象。有關如何實現可激活 對象的示例,請參閱後面的“構造可激活遠程對象”。 7.3.1 ActivationDesc 類 ActivationDesc 含有激活對象所需的信息。它包含對象的激活組標識符、對象的 類名、加載對象代碼的 codebase 路徑(或 URL)及 MarshalledObject(可包含 每次激活期間所用的對象特定初始化數據)。 激活過程中將查詢在激活系統中注冊的描述符以獲取有關的信息,從而用於重新 創建或激活對象。對象的描述符中的 MarshalledObject 將作為第二個參數傳給 遠程對象的構造函數,以供激活過程使用。

package java.rmi.activation; 

public final class ActivationDesc implements java.io.Serializable 
{ 
public ActivationDesc(String className, String codebase, 
java.rmi.MarshalledObject data) 
throws ActivationException; 
public ActivationDesc(String className, String codebase, 
java.rmi.MarshalledObject data, 
boolean restart) 
throws ActivationException; 
public ActivationDesc(ActivationGroupID groupID, 
String className, 
String codebase, 
java.rmi.MarshalledObject data, 
boolean restart); 
public ActivationDesc(ActivationGroupID groupID, 
String className, 
String codebase, 
java.rmi.MarshalledObject data); 
public ActivationGroupID getGroupID(); 
public String getClassName(); 
public String getLocation(); 
public Java.rmi.MarshalledObject getData() 
public boolean getRestartMode(); 
} 
ActivationDesc 的第一個構造函數構造一個對象的對象描述符,這個對象的類是 className(可從 codebase 路徑加載),它的初始化信息(已編組形式)為 d ata。如果使用這種形式的構造函數,則對象的組標識符缺省為該虛擬機 Activa tionGroup 的當前標識符。具有相同 ActivationGroupID 的所有對象都將在同一 虛擬機中被激活。如果當前組是非活動的或無法創建缺省組,則將拋出 Activat ionException。如果 groupID 為 null,則將拋出 IllegalArgumentException。 ? ---------------------------------------------------------------------- ---------- 注意 - 作為創建 ActivationDesc 的副效應,如果該虛擬機的 ActivationGrou p 當前不是活動的,則將創建缺省 ActivationGroup。缺省激活組將 java.rmi. RMISecurityManager 作為安全管理器,並在重新激活時將激活組虛擬機中的屬性 設置為該虛擬機中的當前屬性。如果應用程序需用不同的安全管理器,則在創建 缺省 ActivationDesc 之前必須設置該虛擬機的組。有關如何為虛擬機創建 Act ivationGroup 的詳細信息,參見方法 ActivationGroup.createGroup。 ---------------------------------------------------------------------- ---------- ActivationDesc 第二個構造函數構造對象描述符的方式與第一個構造函數相同, 但必須提供附加的參數 restart。如果對象要求重啟服務,這意味著當激活器重 新啟動時,對象也會自動重新啟動(與根據需要激活的惰性激活相反)。此時, restart 應為 true。如果 restart 為 false,則對象將只是在需要時激活(通 過遠程方法調用)。 ActivationDesc 的第三個構造函數構造一個對象的對象描述符。這個對象的組標 識符為 groupID,它的類名為 className(可從 codebase 路徑加載),它的初 始化信息為 data。所有具有相同 groupID 的對象都將在同一 Java 虛擬機中被 激活。 ActivationDesc 第四個構造函數構造對象描述符的方式與第三個構造函數相同, 但它允許指定重啟模式。如果對象需要重新啟動(定義如上),則 restart 應為 true。 getGroupID 方法返回該描述符所指定對象的組標識符。組可以提供一種將對象聚 合到單一 Java 虛擬機中的方法。 getClassName 方法返回該激活描述符所指定對象的類名。 getLocation 方法返回用於下載該對象的類的 codebase 路徑。 getData 方法返回一個“已編組對象”,該編組對象包含用於初始化(激活)描 述符指定的對象的數據。 getRestartMode 方法在該對象的重啟模式啟用時返回 true,否則返回 false。 7.3.2 ActivationID 類 激活協議利用激活標識符來表示不受時間影響的可激活遠程對象。激活標識符( 類 ActivationID 的實例)含有激活對象所需的若干信息: 對象激活器的遠程引用 對象的唯一標識符。 對象的激活標識符可通過向激活系統注冊對象來得到。可用下述幾種方法之一來 完成注冊(如上所述): 通過 Activatable.register 方法 通過第一個或第二個 Activatable 構造函數(都有三個參數而且注冊並導出對象 ) 通過第一個或第二個 Activatable.exportObject 方法(它們以激活描述符、對 象實現及端口為參數,且都注冊並導出對象)。

package java.rmi.activation; 

public class ActivationID implements java.io.Serializable 
{ 
public ActivationID(Activator activator); 
public Remote activate(boolean force) 
throws ActivationException, UnknownObjectException, Java.rmi. 
RemoteExcep 
tion; 
public boolean equals(Object obj); 
public int hashCode(); 
} 
ActivationID 的構造函數接受參數 activator,該參數指定對激活器(負責激活 與該激活標識符關聯的對象)的遠程引用。ActivationID 的實例是全局唯一的。 activate 方法將激活與該激活標識符關聯的對象。如果 force 參數為 true,激 活器將把遠程對象的任何高速緩存引用視為已過時,從而迫使激活器在激活對象 時與組聯系。如果 force 為 false,則返回可接受的高速緩存值。如果激活失敗 ,則拋出 ActivationException。如果激活器不能識別該對象標識符,則該方法 將拋出 UnknownObjectException。如果對激活器的遠程調用失敗,則拋出 RemoteException。 equals 方法可實現基於內容的相等比較。如果所有的域都相等(完全相同或從各 域的 Object.equals 語義上等價),它將返回 true。如果 p1 和 p2 是類 Act ivationID 的實例,則在 p1.equals(p2) 返回 true 時 hashCode 方法返回相同 的值。 7.3.3 Activatable 類 Activatable 類提供對需要持久訪問而不受時間影響,同時又被系統激活的遠程 對象的支持。類 Activatable 是開發人員用來實現和管理可激活對象的主要應用 程序接口。注意,必須先運行激活系統守護進程 rmid,然後才能注冊和/或激活 對象。


package java.rmi.activation; 
public abstract class Activatable 
extends java.rmi.server.RemoteServer 
{ 
protected Activatable(String codebase, 
java.rmi.MarshalledObject data, 
boolean restart, 
int port) 
throws ActivationException, java.rmi.RemoteException; 

protected Activatable(String codebase, 
java.rmi.MarshalledObject data, 
boolean restart, 
int port, 
RMIClientSocketFactory csf, 
RMIServerSocketFactory ssf) 
throws ActivationException, java.rmi.RemoteException; 

protected Activatable(ActivationID id, int port) 
throws java.rmi.RemoteException; 

protected Activatable(ActivationID id, int port, 
RMIClientSocketFactory csf, 
RMIServerSocketFactory ssf) 
throws java.rmi.RemoteException; 

protected ActivationID getID(); 

public static Remote register(ActivationDesc desc) 
throws UnknownGroupException, ActivationException, 
java.rmi.RemoteException; 

public static boolean inactive(ActivationID id) 
throws UnknownObjectException, ActivationException, 
java.rmi.RemoteException; 

public static void unregister(ActivationID id) 
throws UnknownObjectException, ActivationException, 
java.rmi.RemoteException; 

public static ActivationID exportObject(Remote obj, 
String codebase, 
MarshalledObject data, 
boolean restart, 
int port) 
throws ActivationException, java.rmi.RemoteException; 

public static ActivationID exportObject(Remote obj, 
String codebase, 
MarshalledObject data, 
boolean restart, 
int port, 
RMIClientSocketFactory csf, 
RMIServerSocketFactory ssf) 
throws ActivationException, java.rmi.RemoteException; 

public static Remote exportObject(Remote obj, 
ActivationID id, 
int port) 
throws java.rmi.RemoteException; 

public static Remote exportObject(Remote obj, 
ActivationID id, 
int port, 
RMIClIEntSocketFactory csf, 
RMIServerSocketFactory ssf) 
throws java.rmi.RemoteException; 

public static boolean unexportObject(Remote obj, boolean force) 
throws Java.rmi.NoSuchObjectException; 
} 
可激活遠程對象的實現可能擴展或不擴展類 Activatable。確實擴展 Activatab le 類的遠程對象實現將從超類 java.rmi.server.RemoteObject 中繼承 hashCo de 和 equals 方法中的相應定義。因此,引用同一 Activatable 遠程對象的兩 個遠程引用是相等的(equals 方法將返回 true)。同樣,類 Activatable 的實 例將“等於”該實例的相應 stub 對象(即如果 Object.equals 方法用與該實現 匹配的 stub 對象作為參數進行調用,它將返回 true。反之亦然)。 Activatable 類方法 Activatable 類的第一個構造函數用於在指定 port 上注冊和導出對象(如果 p ort 為零,則選用某個匿名端口)。下載的類代碼對象的 URL 路徑是 coDBase, 其初始化數據是 data。如果 restart 為 true,則對象將在激活器重新啟動或組 失效時自動重新啟動。如果 restart 為 false,則對象將根據需要而激活(通過 對對象的遠程方法調用)。 Activatable 類的具體子類必須調用該構造函數才能在初始構造期間注冊和導出 該對象。作為構造可激活對象時的副效應,遠程對象將被“注冊”到激活系統上 並“導出”(如果 port 為零,則在匿名端口導出)到 RMI 運行時,從而使之可 接受來自客戶機的到來調用。 如果向激活系統注冊對象失敗,則該構造函數將拋出 ActivationException。如 果將對象導出到 RMI 運行時失敗,則將拋出 RemoteException。 第二個構造函數與第一個 Activatable 構造函數相同,但它允許將客戶機和服務 器套接字工廠規范用於與該可激活對象進行通訊。詳細信息,參見“RMI 套接字 工廠”。 第三個構造函數用於激活對象並從指定的 port 將其(用 ActivationID,id)導 出。當對象本身被其專用的“激活”構造函數激活時,Activatable 類的具體子 類必須調用該構造函數。該“激活”構造函數的參數必須是: 對象的激活標識符 (ActivationID) 及 對象的初始化/自舉數據 (MarshalledObject)。 作為構造的副效應,遠程對象將被“導出”到 RMI 運行時中(從指定 port)並 可接受來自客戶機的調用。如果將對象導出到 RMI 運行時失敗,則該構造函數將 拋出 RemoteException。 第四個構造函數與第三個構造函數相同,但它允許將客戶機和服務器套接字工廠 規范用於與該可激活對象進行通訊。 getID 方法返回對象的激活標識符。該方法是受保護的,因而只有子類才能獲取 對象的標識符。 對象的標識符用於報告對象的非活動狀態或注銷對象的激活描述 符。 register 方法為可激活的遠程對象向激活系統注冊對象描述符 desc,從而使該 對象能在需要時被激活。該方法可用於注冊可激活對象而無需先創建該對象。它 返回可激活對象的 Remote stub,因此可加以保存並在今後調用,從而強制首次 創建/激活該對象。如果沒有向激活系統注冊 desc 中的組標識符,該方法將拋出 UnknownGroupException。如果激活系統未運行,則拋出 ActivationException 。最後,如果對激活系統的遠程調用失敗,則拋出 RemoteException。 inactive 方法用於通知系統具有相應激活 id 的對象當前是非活動的。如果已知 該對象當前是活動的,則該對象將不從 RMI 運行時環境中導出(僅在沒有待定的 或執行的調用時),從而可不再接收到來的調用。該調用還將通知該虛擬機的 A ctivationGroup 該對象處於非活動狀態;而該組又將通知其 ActivationMonito r。如果該調用成功,則此後對激活器的激活請求將導致重新激活該對象。如果成 功地阻止該對象被導出(意味著此時它沒有待定或執行調用),則 inactive 方 法返回 true;如果由於待定或進程內調用而不能阻止該對象被導出,則返回 fa lse。如果對象是未知的(它可能是非活動的),則該方法將拋出 UnknownObjec tException;如果組是非活動的,則拋出 ActivationException;如果通知顯示 器的調用失敗,則拋出 RemoteException。如果該對象被認為是活動的但已自己 阻止導出,則該操作仍將成功進行。 unregister 方法用於撤消與 id 關聯的激活描述符的先前注冊。對象不能再用這 個 id 來激活。如果該對象 id 對激活系統來說是未知的,則拋出 UnknownObje ctException。如果激活系統未處於運行狀態,則拋出 ActivationException。如 果對激活系統的遠程調用失敗,則拋出 RemoteException。 第一個 exportObject 方法可被“可激活”但不擴展 Activatable 類的對象顯式 調用,其目的是:a) 向激活系統注冊對象的激活描述符 desc,由所提供的 cod ebase 和 data 構造(因此可激活該對象);b) 從指定 port 導出遠程對象 ob j(如果該 port 為零,則將選擇匿名端口)。對象一旦被導出,即可接收到來的 調用。 該 exportObject 方法返回向激活系統注冊描述符 desc 時所獲得的激活標識符 。如果在虛擬機中激活組不是活動的,則拋出 ActivationException。如果對象 注冊或導出失敗,則拋出 RemoteException。 如果 obj 擴展 Activatable,則不必調用該方法,因為第一個 Activatable 構 造函數將調用該方法。 第二個 exportObject 方法與第一個相同,但它允許將客戶機和服務器套接字工 廠規范用於與該可激活對象進行通訊。 第三個 exportObject 方法將帶標識符 id 的“可激活”遠程對象(不一定是 A ctivatable 類型的)導出到 RMI 運行時,以使對象 obj 能夠接收到來的調用。 如果 port 為零,則將在某個匿名端口導出該對象。 激活時,不擴展 Activatable 類的“可激活”對象應顯式地調用此 exportObje ct 方法。確實擴展 Activatable 類的對象不必直接調用該方法;它將被上面的 第三個構造函數所調用(應從其專用的激活構造函數中調用子類)。 該 exportObject 方法將返回可激活對象的 Remote stub。如果該對象的導出失 敗,則該方法將拋出 RemoteException。 第四個 exportObject 方法與第三個相同,但它允許將客戶機和服務器套接字工 廠規范用於與該可激活對象進行通訊。 unexportObject 方法使遠程對象 obj 不能接收到來的調用。如果參數 force 為 true,則即使有對遠程對象的待定調用或遠程對象在進程內仍有調用,對象也將 被強制阻止導出。如果參數 force 為 false,則只在沒有對對象的待定調用或進 程內沒有調用時它才被阻止導出。如果成功地阻止了該對象的導出,則 RMI 運行 時將從其內部表中刪掉它。使用這種強制方式從 RMI 刪除對象可能會使客戶機持 有遠程對象的過時遠程引用。如果此前沒有將對象導出到 RMI 運行時,則該方法 將拋出 java.rmi.NoSuchObjectException。 構造可激活的遠程對象 為了使對象可激活,“可激活”對象實現類不管是否擴展 Activatable 類,都必 須定義一個特殊的公共構造函數。該公共構造函數帶有兩個參數:激活標識符( 類型為 ActivationID)及激活數據 Java.rmi.MarshalledObject(在注冊時所用 的激活描述符中提供)。當激活組在其虛擬機內激活某個遠程對象時,它將利用 此特殊構造函數來構造對象(後面將作詳細說明)。遠程對象實現可適當用激活 數據來初始化自己。遠程對象也可能想保留其激活標識符,這樣就可以在它變為 非活動狀態(通過對 Activatable. inactive 方法的調用)時通知激活組。 Activatable 構造函數的第一種和第二種形式用於從指定的 port 注冊並導出可 激活對象。最初構造對象時應使用該構造函數;該構造函數的第三種形式將在重 新激活對象時使用。 Activatable 的具體子類必須在最初構造期間調用第一種或第二種構造函數以注 冊並導出對象。 構造函數首先用對象的類名創建一個激活描述符 (ActivationD esc)、對象所提供的 codebase 和 data(其激活組為虛擬機的缺省激活組)。然 後,構造函數將向缺省的 ActivationSystem 注冊該描述符。最後,構造函數在 特定 port 上(如果 port 為零,則選擇匿名端口)將可激活對象導出到 RMI 運 行時中,並將該對象作為 activeObject 報告給本地 ActivationGroup。如果在 注冊或導出的過程中出錯,則構造函數拋出 RemoteException。注意,構造函數 也初始化它的 ActivationID(通過注冊獲得),因此接下來對 protected 方法 getID 的調用將返回對象的激活標識符。 Activatable 構造函數的第三種形式用於從指定的端口導出對象。當 Activatab le 的具體子類被對象自己的“激活”構造函數激活時,必須調用第三種構造函數 。該“激活”構造函數帶兩個參數: 對象的 ActivationID 對象的初始化數據,一個 MarshalledObject 對象 該構造函數只將可激活對象從特定 port(如果 port 為零,則選擇匿名端口)導 出到 RMI 運行時中,而並不通知 ActivationGroup 該對象已是活動對象。因為 正是 ActivationGroup 激活該對象的,因而它自然知道對象已處活動狀態。 下面是遠程對象接口 Server 和擴展 Activatable 類的實現 ServerImpl 的示例:

package examples; 

public interface Server extends java.rmi.Remote 
{ 
public void doImportantStuff() 
throws java.rmi.RemoteException; 
} 

 

public class ServerImpl extends Activatable implements Server 
{ 
// 初始構造、注冊及導出時的構造函數 
public ServerImpl(String codebase, MarshalledObject data) 
throws ActivationException, java.rmi.RemoteException 
{ 
// 向激活系統注冊對象,然後 
// 在匿名端口上導出 
super(codebase, data, false, 0); 
} 

// 激活及導出的構造函數。該構造函數由 
// ActivationInstantiator.newInstance 
// 方法在激活過程中所調用,以構造對象 
public ServerImpl(ActivationID id, MarshalledObject data) 
throws Java.rmi.RemoteException 
{ 
// 調用父類的構造函數以 
// 將對象導出到 RMI 運行時。 
super(id, 0); 
// 初始化對象(例如利用數據) 
} 

public void doImportantStuff() { ... } 
} 

對象將負責導出自己。Activatable 的構造函數負責將對象導出到具有活動引用 類型 UnicastRemoteObject 的 RMI 運行時中,因此,擴展 Activatable 的對象 實現不必關心顯式導出對象(不是調用相應的超類構造函數)的具體細節。如果 對象實現不擴展類 Activatable,則該對象必須通過調用某個 Activatable.exp ortObject 靜態方法來顯式導出該對象。 下例中,ServerImpl 不擴展 Activatable,而是擴展另一個類。因此,ServerI mpl 負責在初始構造和激活過程中導出自己。下述的類定義給出了 ServerImpl 的初始化構造函數及其特殊“激活”構造函數,以及每個構造函數內用於導出對 象的相應調用:

package examples; 

public class ServerImpl extends SomeClass implements Server 
{ 
// 初始創建時的構造函數 
public ServerImpl(String codebase, MarshalledObject data) 
throws ActivationException, java.rmi.RemoteException 
{ 
// 注冊並導出對象 
Activatable.exportObject(this, codebase, data, false, 0); 
} 

// 激活的構造函數 
public ServerImpl(ActivationID id, MarshalledObject data) 
throws Java.rmi.RemoteException 
{ 
// 導出對象 
Activatable.exportObject(this, id, 0); 
} 

public void doImportantStuff() { ... } 
} 

在不創建對象的情況下注冊激活描述符 
要在不創建對象的情況下向激活系統注冊可激活遠程對象,程序員只需為對象注 
冊激活描述符(類 ActivationDesc 的實例)。激活描述符含有一切所需的信息 
,因此必要時激活系統就可以激活該對象。可用以下方法來注冊類 examples.Se 
rverImpl 實例的激活描述符(忽略異常處理): 

Server server;ActivationDesc desc;String codebase = "http://zaphod/cod 
ebase/"; 

MarshalledObject data = new MarshalledObject("some data");desc = new A 
ctivationDesc( "examples.ServerImpl", codebase, data);server = (Server 
)Activatable.register(desc); 

register 調用將返回一個 Remote stub(它是 examples.ServerImpl 對象的 s 
tub),並實現一組與 examples.ServerImpl 所實現的遠程接口相同的遠程接口 
(即 stub 實現遠程接口 Server)。該 stub 對象(上述被強制類型轉換並指派 
給 server 的對象)可作為參數傳給期望實現 examples.Server 遠程接口的對象 
的任何方法調用。 

7.4 激活接口 在 RMI 激活協議中,為使系統運轉正常,激活器必須保證以下兩點: 象所有的系統守護進程一樣,計算機處於打開狀態時激活器必須保持運行狀態 激活器不能重新激活已處在活動狀態的遠程對象。 激活器將為它所要激活的組和對象維護一個相應的信息數據庫。 7.4.1 激活器接口 激活器是參與激活進程的實體之一。如前所述,stub 內的不完善引用將通過調用 激活器的 activate 方法來獲得對可激活遠程對象的“活”引用。激活器接到激 活請求後,就開始查找該激活標識符 id 的激活描述符,以決定要在哪個組中激 活對象,然後調用激活組的實例化器的newInstance 方法(ActivationGroup 的 遠程接口將在後面說明)。激活器將根據需要啟動激活組的執行過程。例如,如 果給定的組描述符的激活組還未運行,則激活器將為該激活組生成一個子虛擬機 ,以便在該新虛擬機中建立該組。 激活器將負責監控和檢測激活組何時失敗,以便將過時的遠程引用從其內部表中 刪去。

package java.rmi.activation; 

public interface Activator extends java.rmi.Remote 
{ 
java.rmi.MarshalledObject activate(ActivationID id, boolean force) 
throws UnknownObjectException, ActivationException, 
Java.rmi.RemoteException; 
} 


activate 方法激活與激活標識符 id 所關聯的對象。如果激活器知道對象已經為 活動對象,且 force 參數為 false,就會立即將含有“活”引用的 stub 返給調 用程序;如果激活器不知道相應的遠程對象是活動的或 force 參數為 true,則 激活器將利用激活描述符信息(先前已為獲得 id 而注冊過)來決定對象應該在 哪個組(虛擬機)中被激活。如果對象組的相應激活 Instantiator 已經存在, 則激活器將通過傳遞 id 和對象的激活描述符來調用該激活實例化器的newInsta nce 方法。 如果對象組描述符的激活實例化器(組)還不存在,則激活器將啟動新的 Activ ationInstantiator 化身執行進程(例如通過生成子進程)。當激活器為某一組 重建 ActivationInstantiator 時,它必須將該組的化身數增一。注意,化身數 從 0 開始。激活系統用化身數來檢測後來的 ActivationSystem.activeGroup 和 ActivationMonitor.inactiveGroup 調用。激活系統將棄去那些化身數小於組的 當前數的調用。 ---------------------------------------------------------------------- ---------- 注意 - 激活器在啟動新的激活組時必須與激活組的標識符、描述符及化身數進行 通訊。激活器將在一個獨立的虛擬機中(例如作為一個獨立的進程或子進程)生 成激活組。因此,它必須將信息傳遞過去,以指定用 ActivationGroup.createG roup 方法來創建該組時所需的信息。激活器並未指定如何將此信息傳給所生成的 進程。可用已編組對象的形式將此信息送到子進程的標准輸入中。 ---------------------------------------------------------------------- ---------- 當激活器接收到激活組的回調(通過 ActivationSystem.activeGroup 方法,該 回調可指明激活組的引用和化身數)時,激活器就可以調用該激活實例化器的 n ewInstance 方法,從而將每個待定的激活請求轉發給該激活實例化器,同時將結 果(一個已編組遠程對象引用、一個 stub)返給每個調用程序。 注意,激活器接收的是 MarshalledObject 對象而不是 Remote 對象。因此,激 活器不需要加載該對象的代碼,也不需要參與該對象的分布式垃圾收集。如果激 活器保留了對遠程對象的強引用,則該激活器將防止該對象在正常的分布式垃圾 收集機制下被當作垃圾而收集。 如果激活失敗,activate 方法將拋出 ActivationException。激活可能會因以下 各種原因而失敗:找不到類、無法與激活組取得聯系等。如果先前沒有為激活標 識符 id 向該激活器注冊激活描述符,則 activate 方法將拋出 UnknownObject Exception。如果對該激活器的遠程調用失敗,則拋出 RemoteException。 7.4.2 ActivationSystem 接口 ActivationSystem 提供了一種為組和可激活對象(這些對象將在這些組中被激活 )注冊的方法。 ActivationSystem 與 Activator 和 ActivationMonitor 都能 密切合作。前者負責激活通過 ActivationSystem 所注冊的對象;後者負責獲取 活動對象、非活動對象及非活動組的有關信息。

package java.rmi.activation; 

public interface ActivationSystem extends java.rmi.Remote 
{ 
public static final int SYSTEM_PORT = 1098; 

ActivationGroupID registerGroup(ActivationGroupDesc desc) 
throws ActivationException, java.rmi.RemoteException; 

ActivationMonitor activeGroup(ActivationGroupID id, 
ActivationInstantiator group, 
long incarnation) 
throws UnknownGroupException, ActivationException, 
java.rmi.RemoteException; 

void unregisterGroup(ActivationGroupID id) 
throws ActivationException, UnknownGroupException, 
java.rmi.RemoteException; 

ActivationID registerObject(ActivationDesc desc) 
throws ActivationException, UnknownGroupException, 
java.rmi.RemoteException; 

void unregisterObject(ActivationID id) 
throws ActivationException, UnknownObjectException, 
java.rmi.RemoteException; 

void shutdown() throws Java.rmi.RemoteException; 
} 

 

---------------------------------------------------------------------- ---------- 注意 - 作為一種安全措施,以上所有方法(registerGroup、activeGroup、unr egisterGroup、registerObject、unregisterObject 和 shutdown)如果被客戶 機所調用,且該客戶機所處主機與激活系統不同,則將拋出 java.rmi.AccessEx ception。該異常是 Java.rmi.RemoteException 的子類。 ---------------------------------------------------------------------- ---------- registerObject 方法用來注冊激活描述符 desc,同時也為可激活遠程對象獲取 激活標識符。 ActivationSystem 為描述符 desc 所指定的對象創建 Activatio nID(激活標識符),並將激活描述符及其關聯的標識符記錄在穩定的存儲庫中以 備將來使用。當 Activator 接到某個特定標識符的 activate 請求時,它就查找 該指定標識符的激活描述符(先前已注冊),並用此信息來激活該對象。如果 d esc 中所引用的組並沒有向該系統注冊,則該方法將拋出 UnknownGroupExcepti on。如果注冊失敗(例如,數據庫更新失敗等),則拋出 ActivationException 。如果遠程調用失敗, 則拋出 RemoteException。 unregisterObject 方法用於刪除激活標識符 id 及以前向 ActivationSystem 注 冊過的相關描述符。該調用完成後,就不能再用對象的激活 id 來激活該對象。 如果對象的 id 是未知的(沒有被注冊),則該方法將拋出 UnknownObjectExce ption。如果注銷失敗(例如,數據庫的更新失敗等),則該方法將拋出 Activa tionException。如果遠程調用失敗,則拋出 RemoteException。 registerGroup 方法用於向激活系統注冊組描述符 desc 所指定的激活組,並返 回指派給該組的 ActivationGroupID。必須先向 ActivationSystem 注冊激活組 ,然後才能在該組中注冊對象。 如果組的注冊失敗,則該方法將拋出 Activati onException。如果遠程調用失敗,則拋出 RemoteException。 activeGroup 方法是來自 ActivationGroup(具有標識符 id)的回調,用以通知 激活系統下列信息:組現在是活動的,而且也是該虛擬機的 ActivationInstant iator。此回調是在 ActivationGroup.createGroup 方法內部進行的,可以獲取 ActivationMonitor。組將用該 ActivationMonitor 就對象和組的狀態(即該組 內的組和對象已變為非活動的)對系統進行更新。 如果該組沒有被注冊,則拋出 UnknownGroupException。如果該組已是活動的,則拋出 ActivationException 。如果對激活系統的遠程調用失敗,則拋出 RemoteException。 unregisterGroup 方法將具有標識符 id 的激活組從激活系統中刪掉。激活組將 進行此回調,以通知激活器應該將該組銷毀。如果此調用順利完成,就將無法再 在該組內注冊和激活對象。有關該組及其相關對象的所有信息都將從系統中刪掉 。如果該組是未經注冊的,則該方法將拋出 UnknownGroupException。如果遠程 調用失敗,則拋出 RemoteException。如果注銷失敗(如數據庫更新失敗等), 則拋出 ActivationException。 shutdown 方法將以適當的異步方式終止激活系統和所有有關的激活進程(激活器 、監控器及組)。由激活守護進程所生成的所有組都將被銷毀,激活守護進程也 將退出。要關閉激活系統守護進程 rmid,請執行命令: rmid -stop [-端口號] 該命令將關閉指定端口上的激活守護進程(如果沒有指定端口,則將關閉缺省端 口上的守護進程)。   7.4.3 ActivationMonitor 類 ActivationMonitor 是 ActivationGroup 特有的,它可通過調用 ActivationSy stem.activeGroup 以報告某個組時獲得(這種調用是在 ActivationGroup.crea teGroup 方法內部進行的)。激活組在出現以下情況時負責通知 ActivationMon itor:它的對象已變成活動對象、非活動對象或該組已整個變成非活動。


package java.rmi.activation; 
public interface ActivationMonitor extends java.rmi.Remote 
{ 

public abstract void inactiveObject(ActivationID id) 
throws UnknownObjectException, RemoteException; 

public void activeObject(ActivationID id, 
java.rmi.MarshalledObject mobj) 
throws UnknownObjectException, java.rmi.RemoteException; 

public void inactiveGroup(ActivationGroupID id, long incarnation) 
throws UnknownGroupException, Java.rmi.RemoteException; 
} 
當激活組中的某個對象變成非活動(停用)時,該激活組將調用其監控器的 ina ctiveObject 方法。激活組通過調用它的 inactiveObject 方法來發現其虛擬機 中的對象(該對象參與了激活)是否已為非活動狀態。 inactiveObject 調用將通知 ActivationMonitor 其所保留的、具有激活標識符 id 的對象的遠程對象引用已不再有效。監控器將把與 id 關聯的引用視為已過 時。由於該引用被當成過時引用,因此後面為同一激活標識符所進行的 activat e 調用將導致遠程對象被重新激活。如果該對象對 ActivationMonitor 未知,該 方法將拋出 UnknownObjectException。如果遠程調用失敗,則拋出 RemoteExce ption。 activeObject 調用通知 ActivationMonitor 與 id 相關聯的對象現在是活動的 。參數 obj 是該對象的 stub 的編組表述。 如果組中的某個對象是通過其它方 法被激活的,而不是由系統直接激活的(也就是說,對象被注冊並自己“激活” 自己),則 ActivationGroup 必須通知其監控器。如果該對象的標識符先前沒有 被注冊,則該方法將拋出 UnknownObjectException。如果遠程調用失敗,則拋出 RemoteException。 inactiveGroup 調用通知監控器由 id 和 incarnation 所指定的組現在已非活動 。一旦下一個要求在該組內激活對象的請求出現時,將用一個更大的化身數來重 新創建該組。當組中所有對象都報告說它們已非活動對象時,該組即變成非活動 組。如果該組的 id 沒有被注冊,或者化身數比該組當前的化身數更小,則該方 法將拋出 UnknownGroupException。如果遠程調用失敗,則拋出 RemoteExcepti on。   7.4.4 ActivationInstantiator 類 ActivationInstantiator 負責創建可激活對象的實例。ActivationGroup 的具體 子類實現 newInstance 方法,以便對在組內創建對象的過程進行控制。


package java.rmi.activation; 

public interface ActivationInstantiator extends java.rmi.Remote 
{ 
public MarshalledObject newInstance(ActivationID id, 
ActivationDesc desc) 
throws ActivationException, Java.rmi.RemoteException; 
} 

為了在該組內重新創建具有激活標識符 id、描述符 desc 的對象,激活器需要調 用實例化器的 newInstance 方法。實例化器負責: 用描述符的 getClassName 方法來決定對象的類; 從由描述符中所獲得的 cadebase 路徑中加載對象的類(用 getLocation 方法) ; 通過調用對象的類的特殊“激活”構造函數創建該類的實例。這種特殊構造函數 帶有兩個參數:一個是對象的 ActivationID,另一個是含有對象特有的初始化數 據的 MarshalledObject; 返回一個含有它所創建的遠程對象的 MarshalledObject。 實例化器還負責在它所創建或激活的對象不再是活動對象時進行報告,因此可以 對其 ActivationMonitor 執行相應的 inactiveObject 調用(詳細信息,參見 ActivationGroup 類)。 如果對象的激活失敗, newInstance 方法將拋出 ActivationException。如果遠 程調用失敗,則該方法將拋出 RemoteException。 7.4.5 ActivationGroupDesc 類 激活組描述符 ActivationGroupDesc 含有創建或重新創建激活組(將在該激活組 中激活相同 Java 虛擬機上的對象)所需的信息。 這種描述符含有: 組的類名, 組的 cadebase 路徑(組的類所在位置), “已編組”對象,它可包含對象特定的初始化數據。 對象的類必須是 ActivationGroup 的具體子類。ActivationGroup 的子類是用 ActivationGroup.createGroup 靜態方法來創建或重新創建的,該靜態方法將調 用含有以下兩個參數的特殊構造函數: 該組的 ActivationGroupID, 該組的初始化數據(在 Java.rmi.MarshalledObject 中)

package java.rmi.activation; 

public final class ActivationGroupDesc implements java.io.Serializable 
{ 

public ActivationGroupDesc(java.util.Properties props, 
CommandEnvironment env);; 

public ActivationGroupDesc(String className, 
String codebase, 
java.rmi.MarshalledObject data, 
java.util.PropertIEs props, 
CommandEnvironment env); 

public String getClassName(); 

public String getLocation(); 

public java.rmi.MarshalledObject getData(); 

public CommandEnvironment getCommandEnvironment(); 

public Java.util.Properties getPropertIEsOverrides(); 

} 
第一個構造函數將創建一個組描述符,它用系統的缺省值來作為組的實現和代碼 位置。各屬性指定了 Java 環境覆蓋(它將覆蓋組實現虛擬機中的系統屬性)。 命令環境可控制啟動子虛擬機時所用的確切命令/選項,也可為 null 以接受 rm id 的缺省值。 第二個構造函數和第一個相同,但它允許指定 Properties 和 CommandEnvironm ent。 getClassName 方法返回組的類名。 getLocation 方法返回 cadebase 路徑,從中可加載該組的類。 getData 方法以編組形式返回組的初始化數據。 getCommandEnvironment 方法返回命令環境(可能為 null)。 getPropertIEsOverrides 方法返回該描述符的屬性覆蓋(可能為 null)。   7.4.6 ActivationGroupDesc.CommandEnvironment 類 CommandEnvironment 類允許對缺省系統屬性進行覆蓋,並可為 ActivationGrou p 指定由實現所定義的選項。

public static class CommandEnvironment 

implements java.io.Serializable 
{ 
public CommandEnvironment(String cmdpath, String[] args); 
public boolean equals(Java.lang.Object); 
public String[] getCommandOptions(); 
public String getCommandPath(); 
public int hashCode(); 
} 
  
構造函數將用所給的命令 cmdpath 和另一個命令行選項 args 創建 CommandEnv ironment。 equals 實現對命令環境對象的內容等效操作。對 hashCode 方法進行適當的實現 可在必要時將 CommandEnvironment 對象儲存在散列表中。 getCommandOptions 方法返回環境對象的命令行選項。 getCommandPath 方法返回環境對象的命令字符串。 7.4.7 ActivationGroupID 類 注冊過的激活組的標識符可有以下幾個用途: 在激活系統中對該組進行唯一標識 含有對該組的激活系統的引用,因而必要時該組能與其激活系統聯系。 ActivationGroupID 將在調用 ActivationSystem.registerGroup 時被返回,並 用來在該激活系統內標識該組。當創建或重新創建激活組時,該組標識符將被作 為參數傳給激活組的特殊構造函數。

package java.rmi.activation; 

public class ActivationGroupID implements Java.io.Serializable 
{ 
public ActivationGroupID(ActivationSystem system); 

public ActivationSystem getSystem(); 

public boolean equals(Object obj); 

public int hashCode(); 
} 
ActivationGroupID 構造函數創建唯一的組標識符。該標識符的 ActivationSys tem 是 system。 getSystem 方法返回組的激活系統。 hashCode 方法返回組標識符的散列碼。兩個指向同一遠程組的組標識符將具有相 同的散列碼。 equals 方法比較兩個組標識符內容的等效性。如果以下兩個條件均成立,該方法 將返回 true: 1) 兩個唯一標識符在內容上等價。2) 各標識符中指定的激活系 統都引用同一遠程對象。   7.4.8 ActivationGroup 類 ActivationGroup 負責在其組中創建“可激活”對象的新實例,並在出現下列情 況時通知其 ActivationMonitor: 其對象變成活動或非活動,或者該組整體變成 非活動。 ActivationGroup 最初是由以下方法之一創建的: 作為創建對象的“缺省” ActivationDesc 的副效應而創建 通過對 ActivationGroup.createGroup 方法的顯式調用而創建 作為在組(該組中僅 ActivationGroupDesc 被注冊過)中激活第一個對象時的副 效應而創建。 只有激活器才能重新創建 ActivationGroup。必要時,激活器將為每個已注冊的 激活組生成一個獨立的虛擬機(例如作為子進程)並將激活請求定向到相應的組 。生成虛擬機的方式與實現有關。激活組是通過 ActivationGroup.createGroup 靜態方法來創建的。createGroup 方法對即將創建的組有兩個要求: 1) 該組必 須是 ActivationGroup 的具體子類;2) 該組必須有一個取以下兩個參數的構造 函數: 該組的 ActivationGroupID, 該組的初始化數據(包含在 MarshalledObject中) 創建完畢,ActivationGroup 的缺省實現將在創建該組的 ActivationGroupDesc 時把系統屬性設置為強制系統屬性,並將安全管理器設置為 Java.rmi.RMISecu rityManager。如果應用程序要求當對象在組中被激活時設置某些特定的屬性,則 該應用程序應在創建 ActivationDesc 之前(缺省 ActivationGroupDesc 創建前 )設置這些屬性。

package java.rmi.activation; 

public abstract class ActivationGroup 
extends UnicastRemoteObject 
implements ActivationInstantiator 
{ 
protected ActivationGroup(ActivationGroupID groupID) 
throws java.rmi.RemoteException; 

public abstract MarshalledObject newInstance(ActivationID id, 
ActivationDesc desc) 
throws ActivationException, java.rmi.RemoteException; 

public abstract boolean inactiveObject(ActivationID id) 
throws ActivationException, UnknownObjectException, 
java.rmi.RemoteException; 

public static ActivationGroup createGroup(ActivationGroupID id, 
ActivationGroupDesc desc, 
long incarnation) 
throws ActivationException; 

public static ActivationGroupID currentGroupID(); 

public static void setSystem(ActivationSystem system) 
throws ActivationException; 

public static ActivationSystem getSystem() 
throws ActivationException; 

protected void activeObject(ActivationID id, 
java.rmi.MarshalledObject mobj) 
throws ActivationException, UnknownObjectException, 
java.rmi.RemoteException; 

protected void inactiveGroup() 
throws UnknownGroupException, Java.rmi.RemoteException; 
} 
激活器通過調用激活組的 newInstance 方法來激活具有激活描述符 desc 的對象 。激活組負責: 利用描述符的 getClassName 方法來確定該對象的類; 通過 getLocation 方法從由描述符中所得到的 URL 路徑中加載該類; 通過調用該對象類的特殊構造函數來創建該類的實例。該構造函數取以下兩個變 量:對象的 ActivationID 和含有對象初始化數據的 MarshalledObject; 將剛創建的遠程對象的序列化版本返給激活器。 如果無法創建所給描述符的實例,該方法將拋出 ActivationException。 對該組的 inactiveObject 方法的調用是通過調用 Activatable.inactive 方法 來間接進行的。當遠程對象停用時(該對象被認為非活動的),該對象的實現必 須調用 Activatable 的 inactive。如果對象在非活動時不調用 Activatable.i nactive,則該對象將永遠不會被作為垃圾收集,因為組將對其所創建的對象保留 強引用。 組的 inactiveObject 方法可阻止從 RMI 運行時中導出與 id 關聯的遠程對象( 僅當沒有對該對象的待定或正在執行的調用時)。使該對象將無法再接收到來的 RMI 調用。如果該對象當前還有待定或正在執行的調用,inactiveObject 將返 回 false 且不采取任何動作。 如果 unexportObject 操作成功,意味著該對象沒有待定或正在執行的調用。此 時組將通過監控器的 inactiveObject 方法通知它的 ActivationMonitor 該遠程 對象當前是非活動的,以便激活器在接到下一激活請求時即重新將該遠程對象激 活。如果操作成功,inactiveObject 將返回 true。如果該對象被 ActivationG roup 認為是活動的但已被阻止導出,操作將仍有可能成功。 如果激活組不知道該對象(例如該對象先前已被報告為是非活動的,或者從未通 過該激活組來激活該對象),則 inactiveObject 方法將拋出 UnknownObjectEx ception。如果非活動操作失敗(例如,對激活器或激活組的遠程調用失敗),則 將拋出 RemoteException。 createGroup 方法將為當前虛擬機創建和設置激活組。只有在激活組是當前未設 定的情況下才能對它進行設置。當 Activator 為了執行到來的 activate 請求而 啟動某一激活組的重新創建過程時,該激活組即通過 createGroup 方法進行設置 。組必須先向 ActivationSystem 注冊一個描述符,然後才能用該方法(將注冊 中得到的 ActivationID 傳給它)來創建該組。 由 ActivationGroupDesc(即 desc)指定的組必須是 ActivationGroup 的具體 子類並具有公共構造函數。該公共構造函數取兩個參數:一個是組的 Activatio nGroupID;另一個是 MarshalledObject,它含有組的初始化數據(從組的Activ ationGroupDesc 中獲得的)。注意: 如果應用程序要創建自己的自定義激活組 ,該組必須在構造函數中設置安全管理器。否則將不能在該組中激活對象。 創建完組後,即通知 ActivationSystem 該組已通過調用 activeGroup 方法(該 方法將返回組的 ActivationMonitor)而被激活。應用程序不必單獨調用 activ eGroup,因為 createGroup 方法將負責這一回調。 一旦組被創建,對 currentGroupID 方法的後續調用都將返回該組的標識符,直 到該組變成非活動組為止。那時,currentGroupID 方法將返回 null。 參數 incarnation 表示當前的組化身數,也就是該組被激活的次數。一旦組被成 功創建,化身數就被用作 activeGroup 方法的參數。化身數從 0 開始。如果該 組已經存在,或在組的創建過程中出錯,createGroup 方法將拋出 ActivationE xception。 setSystem 方法用於設置虛擬機的 ActivationSystem (system)。只有當前沒有 組為活動組時才能對激活系統進行設置。如果沒有通過顯式調用 setSystem 來設 置激活系統,則 getSystem 方法將嘗試通過在 Activator 的注冊服務程序中查 找名稱 java.rmi.activation.ActivationSystem 來獲得對 ActivationSystem 的引用。缺省情況下,查找激活系統所用的端口號將由 ActivationSystem.SYST EM_PORT 定義。通過設置屬性 Java.rmi.activation.port 可將該端口覆蓋掉。 如果調用 setSystem 時激活系統已經設置好,則該方法將拋出 ActivationExce ption。 getSystem 方法返回該虛擬機的激活系統。激活系統可由 setSystem 方法(前述 )設置。 activeObject 方法是一個受保護的方法。子類將用它來對組監控器進行 active Object 回調,以通知監控器具有指定激活 id 且其 stub 包含在 mobj 中的遠程 對象現在是活動的。這一調用只是轉發給組的 ActivationMonitor。 inactiveGroup 方法是一個受保護的方法。子類用它來通知組監控器該組已變成 非活動的。當組中每個參與虛擬機中激活活動的對象都變成非活動時,子類就進 行此調用。 7.4.9 MarshalledObject 類 MarshalledObject 是某個對象的容器,它允許在進行 RMI 調用時將該對象當作 一個參數來傳遞,但它延遲該對象在接收端上的序列化恢復,直到應用程序明確 地請求該對象(通過調用該容器對象)。包含在該 MarshalledObject 中的可序 列化對象是用相同的語義(該語義作為 RMI 調用中的參數來傳遞)來序列化和序 列化恢復的(請求時)。也就是說,MarshalledObject 中的任一遠程對象都可表 示為其 stub 的序列化實例。MarshalledObject 所包含的對象可以是遠程對象、 非遠程對象或遠程對象和非遠程對象的完整圖形。 當對象被放入 MarshalledObject 的 wrapper 中時,該對象的序列化形式將被注 釋為 cadebase URL(可從中加載類);同樣,當從對象的 MarshalledObject 的 wrapper 中取回該對象時,如果本地沒有該對象的代碼,則使用該 URL(序列 化時所注解的)來定位和加載該對象類的字節代碼。


package java.rmi; 

public final class MarshalledObject implements java.io.Serializable 
{ 
public MarshalledObject(Object obj) throws java.io.IOException; 

public Object get() 
throws Java.io.IOException, ClassNotFoundException; 

public int hashCode(); 

public boolean equals(); 
} 
MarshalledObject 的構造函數將可序列化的對象 obj 作為單一參數,並將對象 的編組表示存放在字節流中。對象的編組表示保存了對象在 RMI 調用時所傳遞的 語義: 流中的每個類都被注解為其 cadebase URL,以便在重構該對象(通過調用 get 方法)時可以找到各個類的字節代碼並進行加載; 遠程對象由它們的代理服務器 stub 所代替。 當把類 MarshalledObject 的實例寫到 java.io.ObjectOutputStream 中時,所 含對象的編組形式(在構造中創建)亦被寫到流中。因此,只有字節流才被序列 化。 當從 Java.io.ObjectInputStream 中讀取 MarshalledObject 時,並不把所包含 的對象序列化恢復為一個具體對象;該對象將一直保持其編組表示,直到該已編 組對象的 get 方法被調用為止。 get 方法總是要用所含對象的編組形式來重新構造該對象。內部表示將用解編參 數(用於 RMI 調用)所用的語義來進行序列化恢復。因此,對象表示的序列化恢 復將用嵌入對象序列化流中的 URL 注解來加載類的代碼(如果本地沒有該代碼) 。 對象編組表示的 hashCode 與傳遞給構造函數的對象相同。如果進行比較的對象 的編組表示是等價的,則 equals 方法將返回 true。該 equals 方法所采用的比 較將忽略類的 cadebase 注解,即除了序列化表示中各個類的 cadebase 外,只 要兩個對象具有相同的序列化表示,則這兩個對象就是等價的。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved