?? rmi規范說明5.txt
字號:
RMI規范--第五章
服務器接口
java.rmi.server 包包含通常用于實現遠程對象的接口與類。
主題:
RemoteObject 類
RemoteServer 類
UnicastRemoteObject 類
Unreferenced 接口
RMISecurityManager 類
RMIClassLoader 類
LoaderHandler 接口
RMI 套接字工廠
RMIFailureHandler 接口
LogStream 類
stub 和 skeleton 編譯器
5.1 RemoteObject 類
類 java.rmi.server.RemoteObject 將 java.lang.Object 行為實現于遠程
對象。實現方法 hashCode 和 equals 將允許將遠程對象引用存儲在散列表中
進行比較。如果兩個 Remote 對象引用同一個遠程對象,則方法 equals 的返
回值為 true。它負責比較遠程對象的遠程對象引用。
方法 toString 返回一個說明遠程對象的字符串。該字符串的內容和語法與實
現有關且可變。
java.lang.Object 中的其它方法保留了它們的原始實現。
package java.rmi.server;
public abstract class RemoteObject
implements java.rmi.Remote, java.io.Serializable
{
protected transient RemoteRef ref;
protected RemoteObject();
protected RemoteObject(RemoteRef ref);
public RemoteRef getRef();
public static Remote toStub(java.rmi.Remote obj)
throws java.rmi.NoSuchObjectException;
public int hashCode();
public boolean equals(Object obj);
public String toString();
}
因為 RemoteObject 是抽象類,所以無法實例化。因此,RemoteObject 的構
造函數必須從子類實現中調用。第一個 RemoteObject 構造函數將創建帶空的
遠程引用的 RemoteObject。第二個 RemoteObject 構造函數將創建帶給定遠
程引用 ref 的 RemoteObject。
方法 getRef 返回該遠程對象的遠程引用。
方法 toStub 返回一個遠程對象 obj 的 stub 并作為參數傳送。該操作僅在
已經導出遠程對象實現后才有效。如果找不到遠程對象的 stub,該方法就拋出
NoSuchObjectException。
5.1.1 RemoteObject 類覆蓋的對象方法
java.lang.Object 類中用于方法 equals、hashCode 和 toString 的缺省實
現不適用于遠程對象。因此,RemoteObject 類提供了這些方法在語義上更合適
于遠程對象的實現。
equals 和 hashCode 方法
為將遠程對象用作散列表中的主鍵,我們必須在遠程對象實現中覆蓋 equals 和
hashCode 方法,這些方法是由類 java.rmi.server.RemoteObject 覆蓋的:
java.rmi.server.RemoteObject 類實現 equals 方法決定了兩個對象的引用
是否相等,而不是兩個對象的內容是否相等。這是因為決定內容是否相等時需要
遠程方法調用,而 equals 的簽名不允許拋出遠程異常。
對于所有引用同一底層遠程對象的遠程引用,java.rmi.server.RemoteObject
類實現的 hashCode 方法返回同一個值(因為對相同對象的引用被認為是相等
的)。
toString 方法
toString 方法被定義為返回表示對象的遠程引用的字符串。字符串的內容視引
用的類型而定。單體(單路傳送)對象的當前實現一個對象標識符以及與傳輸層
有關的該對象的其他信息(例如主機名和端口號)。
clone 方法
只有在對象支持 java.lang.Cloneable 接口時才能用 Java 語言的缺省機制
來復制。由 rmic 編譯器生成的遠程對象的 stub 將被聲明為終態,且不實現
Cloneable 接口,因此無法復制 stub。
5.1.2 序列化形式
RemoteObject 類實現專門的(私用)方法 writeObject 和方法 readObject,
它們由對象序列化機制調用來處理向 java.io.ObjectOutputStream 中序列化
數據。RemoteObject 的序列化形式由下列方法寫入:
private void writeObject(java.io.ObjectOutputStream out)
throws java.io.IOException, java.lang.ClassNotFoundException;
如果 RemoteObject 的遠程引用域 ref 為空,則該方法拋出
java.rmi.MarshalException。
如果遠程引用 ref 為非空:
ref 的類通過調用其 getRefClass 方法來獲得,該方法通常返回遠程引用類的
非打包全名。如果返回的類名為非空:
ref 的類名將以 UTF 格式寫到流 out 中。
調用 ref 的方法 writeExternal,傳遞的參數為流 out,從而使 ref 可以將
其外部表示法寫到流中。
如果 ref.getRefClass 返回的類名為空:
則將一個 UTF 格式的空字符串寫到流 out 中。
ref 被序列化到流 out(即利用 writeObject)。
序列化恢復時,RemoteObject 的狀態將由 ObjectInputStream 調用該方法利
用其序列化形式進行重構:
private void readObject(java.io.ObjectInputStream in)
throws java.io.IOException, java.lang.ClassNotFoundException;
首先,ref 的類名(UTF 字符串)將從流 in 中讀出。如果類名為空字符串:
則從流中讀出對象,然后將 ref 初始化為該對象(即通過調用 in.readObject)
如果類名為非空:
則 ref 的完整類名由字符串 java.rmi.server.RemoteRef.packagePrefix 的
值和“.”加上從流中讀取的類名相連接而成。
創建 ref 類的實例(利用上述完整類名)。
該新實例(成為 ref 域)從流 in 中讀取其外部形式。
2 RemoteServer 類
java.rmi.server.RemoteServer 類是服務器實現類
java.rmi.server.UnicastRemoteObject
和 java.rmi.activation.Activatable 的通用超類。
package java.rmi.server;
public abstract class RemoteServer extends RemoteObject
{
protected RemoteServer();
protected RemoteServer(RemoteRef ref);
public static String getClientHost()
throws ServerNotActiveException;
public static void setLog(java.io.OutputStream out);
public static java.io.PrintStream getLog();
}
因為 RemoteServer 是抽象類,所以將無法實例化。因此,必須從子類實現中
調用某一 RemoteServer 的構造函數。第一個 RemoteServer 構造函數將創建
帶空遠程引用的 RemoteServer。第二個 RemoteServer 構造函數將創建帶給
定遠程引用 ref 的 RemoteServer。
getClientHost 方法允許一個活動方法確定當前線程中活動的遠程方法是由哪
臺主機初始化的。如果當前線程中沒有活動的遠程方法,則拋出異常 ServerNot
ActiveException。
setLog 方法將 RMI 調用記錄到指定輸出流中。如果輸出流為空,則關閉調用
日志。getLog 方法返回 RMI 調用日志流,從而使特定于應用程序的信息以同
步方式寫到調用日志中。
5.3 UnicastRemoteObject 類
類 java.rmi.server.UnicastRemoteObject 支持創建并導出遠程對象。該類
實現的遠程服務器對象具有下列特征:
對這種對象的引用至多僅在創建該遠程對象的進程生命期內有效。
通過 TCP 傳輸與遠程對象通信。
調用、參數和結果使用流協議在客戶機和服務器之間進行通信。
package java.rmi.server;
public class UnicastRemoteObject extends RemoteServer
{
protected UnicastRemoteObject()
throws java.rmi.RemoteException;
protected UnicastRemoteObject(int port)
throws java.rmi.RemoteException;
protected UnicastRemoteObject(int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws java.rmi.RemoteException;
public Object clone()
throws java.lang.CloneNotSupportedException;
public static RemoteStub exportObject(java.rmi.Remote obj)
throws java.rmi.RemoteException;
public static Remote exportObject(java.rmi.Remote obj, int port)
throws java.rmi.RemoteException;
public static Remote exportObject(Remote obj, int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws java.rmi.RemoteException;
public static boolean unexportObject(java.rmi.Remote obj, boolean force)
throws java.rmi.NoSuchObjectException;
}
5.3.1 構造新遠程對象
遠程對象實現(實現一個或多個遠程接口的實現)必須被創建和導出。導出遠程
對象使得對象能接受來自客戶機的到來的調用。作為 UnicastRemoteObject
導出的遠程對象,其導出涉及在 TCP 端口監聽(注意,多個遠程對象可以接受
同一端口的到來的調用,因此沒必要在新的端口上監聽)。遠程對象實現可以擴
展類 UnicastRemoteObject 以使用其導出對象的構造函數,或者擴展其它類
(或者根本不擴展)并通過 UnicastRemoteObject 的 exportObject 方法導
出對象。
無參數的構造函數將創建遠程對象并在匿名(或任意)端口上導出,而這將在運
行時進行選擇。第二種形式的構造函數帶單個參數(即 port),它指定遠程對
象接受到來的調用的端口號。第三種構造函數創建的遠程對象在指定端口上通過
RMIServerSocketFactory 創建的 ServerSocket 接受到來的調用;客戶機
通過由 RMIClientSocketFactory 提供的 Socket 與遠程對象建立連接。
5.3.2 導出并非由 RemoteObject 擴展而來的實現
exportObject 方法(任何形式)可用于導出不是由擴展 UnicastRemoteObject
類實現的簡單對等遠程對象。第一種形式的 exportObject 方法帶單個參數
(即 obj),它是接受到來的 RMI 調用的遠程對象;該 exportObject 方法
在匿名(或任意)端口上導出遠程對象,而這將在運行時進行選擇。第二種形式
的 exportObject 方法帶兩個參數,分別是遠程對象 obj 和 port。port 是
遠程對象接受到來的調用的端口號。第三種 exportObject 方法用指定的
RMIClientSocketFactory、csf 和 RMIServerSocketFactory、ssf 在指定
port 上導出對象 obj。
在作為參數或返回值傳入 RMI 調用前,必須導出對象,否則當試圖把“未導出
的”對象作為參數或返回值傳遞給一個遠程調用時,將會拋出
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -