日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java分布式对象——远程方法中的参数和返回值+远程对象激活

發布時間:2023/12/3 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java分布式对象——远程方法中的参数和返回值+远程对象激活 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【0】README

1)本文文字描述轉自 core java volume 2, 旨在學習 java分布式對象——遠程方法中的參數和返回值+遠程對象激活 的相關知識;

【1】遠程方法中的參數和返回值

1) 在開始進行遠程方法調用時,調用參數需要從客戶端的虛擬機中移動到服務器的虛擬機中。
2) 對于從一個虛擬機向另一個虛擬機傳值,我們將其區分成兩種情況:傳遞遠程對象和傳遞非遠程對象。


【1.1】傳遞遠程對象

1)當一個對遠程對象的引用從一個虛擬機傳遞到另一個虛擬機時,該遠程對象的發送者和接收者都將持有一個對同一個實體的引用。這個引用并非是一個內存位置(內存位置在單個虛擬機內才有意義),而是由網絡地址和該遠程對象的唯一標識符構成的。這個信息給封裝在存根對象中。

  • 1.1) 需要始終牢記的是: 在遠程引用上的方法調用明顯比在本地引用上的方法調用執行得慢,并且潛在地也更不可靠。

【1.2】傳遞非遠程對象

Conclusion)總結一下,在虛擬機之間傳遞值有兩種機制:

  • c1)實現了Remote接口: 的類的對象將作為遠程引用傳遞;
  • c2)實現了Serializable接口: 但是沒有實現Remote接口的類的對象將使用序列化進行復制;

Attention)

  • A1)這兩種機制都是自動化的,而且不需要任何程序員的干預。
  • A2)請記住,序列化對于大型對象來說會比較慢,而且遠程方法不能改變被序列化的參數。
  • A3)當然,你可以通過傳遞遠程引用來避免這些問題。但是這么做代價太大: 在遠程引用上調用方法與調用本地方法相比,代價高得多。
  • A4)意識到這些開銷有助于在設計遠程服務時進行選擇。

1)看個荔枝: 我們的下一個示例程序將展示遠程和可序列化對象的傳遞。我們將Warehouse接口修改為代碼11-5的樣子,如果給定關鍵詞列表,這個倉庫將返回最佳匹配的Product。

public interface Warehouse extends Remote
{
double getPrice(String description) throws RemoteException;
Product getProduct(List keywords) throws RemoteException;
} // getProduct方法的參數具有List類型。因此,參數值必須屬于實現了List接口的可序列化的類,例如ArrayList。

Attention) Product類是可序列化的,服務器構建了一個Product對象,而客戶端獲取了它的一個副本(參見圖11-7)。


【1.3】動態類加載

1)應用背景:關鍵詞列表發送到了服務器,而且倉庫也返回了Product類的一個實例。當然,客戶端程序在編譯時需要Product.class類文件。但是,只要我們的服務器程序無法找到關鍵詞的匹配,它就會返回一件肯定讓每個人都很高興的產品:《Java核心技術》這本書。這個對象是Book類的實例,而Book類是Product的子類。
2)problem+solution:

  • 2.1)problem: 當客戶端編譯時,它也許從未看到過Book類。但是在運行時,它需要能夠執行覆蓋了Product方法的Book方法,這說明客戶端需要擁有在運行時加載額外類的能力。
  • 2.2)solution: 客戶端使用了與RMI注冊表相同的機制,即類由web服務器提供服務,RMI服務器類將URL傳遞給客戶端,客戶端創建要求下載這些類的HTTP請求。

3)problem+solution:

  • 3.1)problem: 只要一個程序從網絡位置加載新的代碼,就會涉及安全問題。
  • 3.2)solution:正是由于這個原因,我們需要在動態加載類的RMI應用中使用安全管理器。

4) 安裝安全管理器:使用RMI的程序應該安裝一個安全管理器,去控制動態加載類的行為。可以用下面的指令安裝:

System.setSecurityManager(new SecurityManager());

5)problem+solution:

  • 5.1)problem: 默認情況下,SecurityManager會限制程序中所有的代碼去建立網絡連接,但是,我們的程序需要建立到三個遠程位置的網絡連接(connection):

    • c1)加載遠程類的Web服務器;
    • c2) RMI注冊表;
    • c3)遠程對象;
  • 5.2)solution:為了允許這些操作,需要提供一個策略文件。

  • 5.3)看個荔枝: 下面的策略文件允許一個應用建立任何到端口號至少為1024的某個端口的網絡連接。(RMI端口默認為1099,遠程對象使用的端口也大于等于1024。我們使用8080端口來下載類。)

    grant
    {
    permission java.net.SocketPermission
    “*:1024-65535”, “connect”;
    };


6)需要通過將java.security.policy屬性設置為這個策略文件名,來指示安全管理器去讀取該策略文件。
  • 6.1)可以使用下面這個調用:

    System.setProperty(“java.security.policy”, “rmi.policy”);

  • 6.2)或者,可以在命令行指定系統屬性設置:

    -Djava.security.policy=rmi.policy

7)為了運行示范程序,請確保已經關閉了在前面的示范程序中啟動的RMI注冊表、Web服務器和服務器程序。打開四個控制臺窗口,然后執行下面的步驟:

  • 7.1) 編譯接口、實現、客戶端和服務器類的源文件。
    javac *.java
  • 7.2) 創建三個目錄:client、server和download,然后按下面這樣組裝它們:

    client/
    WarehouseClient.class
    Warehouse.class
    Product.class
    client.policy
    server/
    Warehouse.class
    Product.class
    Book.class
    WarehouseImpl.class
    WarehouseServer.class
    server.policy
    download/
    Warehouse.class
    Product.class
    Book.class

  • 7.3) 在第一個控制臺窗口中,轉到download目錄下,啟動NanoHTTP

  • 7.4) 在第二個控制臺窗口中,轉到server目錄下,啟動服務器: java -Djava.rmi.server.codebase=http://localhost:8080/ WarehouseServer
  • 7.5) 在第三個控制臺窗口中,轉到client目錄下,運行客戶端:

8)看個荔枝:

  • 遠程對象傳送全部源代碼參見:https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter11/rmi_transfer

【1.4】具有多重接口的遠程引用(遠程類實現多個接口)

1)可以使用instanceof操作符來查看一個特定的遠程對象是否實現了某個接口。假設我們通過一個類型為Warehouse的變量得到了一個遠程對象:

Warehouse location = product.getLocation();

2)這個遠程對象可能是一個服務中心,但也可能不是。要確定到底是不是,可以使用下面的測試:

if (location instanceof ServiceCenter)

3)如果測試通過,就可以將location轉型為ServiceCenter,并調用getReturnAuthorization方法。


【1.5】遠程對象與 equals,hashCode 和 clone 方法

1) 插入集中的對象必須覆寫equals方法。如果是散列集或散列映射表,則需定義hashCode方法。
2)不能在遠程接口中定義equals方法 和 hashCode 方法:然而,比較遠程對象時有一個問題。如果要比較兩個遠程對象是否具有相同的內容,調用equals則必須聯系包含這些對象的服務器,然后比較它們的內容。而該調用可能會失敗。但是,Object類中的equals方法并未聲明會拋出RemoteException異常,而遠程接口中的所有方法都必須拋出該異常。因為子類的方法不能比它覆寫的父類的方法拋出更多的異常,所以不能在遠程接口中定義equals方法。hashCode也是這樣。
3)存根對象的equals 方法 和 hashCode 方法: 相反,存根對象的equals和hashCode方法只是查看遠程對象的位置。只要它們指向相同的遠程對象,equals方法就認為兩個存根相同。
Conclusion)總之,可以使用集與散列表中的遠程引用,但是必須記住,對它們進行等價測試以及散列計算并不會考慮遠程對象的內容。你不能直接克隆遠程引用。


【2】 遠程對象激活(延遲構造遠程對象)

1)激活機制: 激活機制(activation)允許延遲構造遠程對象,僅當至少有一個客戶端調用遠程對象上的遠程方法時,才真正去構造該遠程對象。 (干貨——激活機制定義)
2)引用激活機制的client 和 server:

  • 2.1)client:要享用激活機制的好處,客戶端代碼完全無需改動。客戶端只是簡單的請求一個遠程引用,然后通過它進行調用而已。
  • 2.2)server:然而,服務器程序則需由一個激活程序來代替。該程序構造了對象的激活描述符(activation descriptors),這樣的對象可以延遲構造,并且該程序通過命名服務為遠程方法調用綁定了接收者。第一次對這樣的對象進行方法調用時,激活描述符中的信息將會用來構造該對象。

3)應用激活機制的遠程對象: 必須繼承Activatable類而不是UnicastRemoteObject類,當然,還需實現一個或多個遠程接口。例如,

class WarehouseImpl
extends Activatable
implements Warehouse
{

}

4)因為對象的構造是延遲進行的,所以它必須以標準方式實現。因此,構造器必須包含以下兩個參數(params):

  • p1)一個激活ID(只需傳遞給父類的構造器)
  • p2)一個包含所有構造信息的對象,包裝為MarshalledObject;

  • 4.1)在構建激活描述符時,需要像下面這樣從構造信息中構造一個MarshalledObject:
    MarshalledObject param = new MarshalledObject(constructionInfo);

  • 4.2)在實現對象的構造器中,使用MarshalledObject類的get方法來獲得反序列化之后的構造信息:
    T constructionInfo = param.get();

5)看個荔枝:為了演示激活,我們修改了WarehouseImpl類,使得構造信息是一個由描述和價格構成的映射表。這個信息被包裝到了MarshalledObject中,并且在構造器中被拆包出來:

public WarehouseImpl(ActivationID id, MarshalledObject<Map<String, Double>> param) throws RemoteException, ClassNotFoundException, IOException { super(id, 0); prices = param.get(); System.out.println("Warehouse implementation constructed."); }
  • 5.1)將0作為父類構造器的第二個參數: 代表RMI類庫應該分配一個合適的端口號作為監聽端口。構造器會打印一個信息,這樣就可以看到所需的產品對象已經被激活了。
  • Attention) 其實遠程對象不是一定要繼承Activatable類,例如,可以將下面的靜態方法調用放在服務器類的構造器中。

    Activatable.exportObject(this, id, 0)


6)如何構建激活程序
  • step1)需要定義一個激活組。一個激活組描述了啟動遠程對象所在的虛擬機所需的公共參數,其中最重要的參數是安全策略。
  • step2) 然后如下構造一個激活組描述符:

    Properties props = new Properties();
    props.put(“java.security.policy”, “/server/server.policy”);
    ActivationGroupDesc group = new ActivationGroupDesc(props, null);
    //第二個參數描述了一個特殊的命令選項,在這個例子中不需要任何選項,所以我們傳遞了一個null引用。

  • step3)創建一個組ID
    ActivationGroupID id = ActivationGroup.getSystem().registerGroup(group

  • step4) 構造一個激活描述符了。對于需要構造的每一個對象,都應該包括以下內容(contents):

    • c1)激活組ID,對象將在與其對應的虛擬機上被構造;
    • c2)類的名字(例如”ProductImpl”或”com.mycompany.MyClassImpl”);
    • c3) URL字符串,由該URL加載類文件。這應該是基本URL,不含包的路徑;
    • c4)編組后的構造信息。

7)看個荔枝:

MarshalledObject param = new MarshalledObject(constructionInfo);
ActivationDesc desc = new ActivationDesc(id, “WarehouseImpl”,
“http://myserver.com/download/“, param);

  • 7.1)將此描述符傳遞給靜態的Activatable.register方法。它返回一個對象,該對象實現了實現類的遠程接口。可以使用命名服務綁定該對象:

    Warehouse centralWarehouse = (Warehouse) Activatable.register(desc);
    namingContext.bind(“rmi:central_warehouse”, centralWarehouse);

  • Attention) 與前例的服務器程序不同,激活程序在注冊與綁定激活接收者之后就會退出。僅當遠程方法調用第一次發生時,才會構造遠程對象。

8)荔枝:

  • 8.1)啟動遠程對象激活程序,可按一下steps 進行:

    • step1) 編譯所有文件;
    • step2)發布類文件:

      client/
      ????????WarehouseClient.class
      ????????Warehouse.class
      server/
      ???????? WarehouseActivator.class
      ???????? Warehouse.class
      ???????? WarehouseImpl.class
      ???????? server.policy
      download/
      ???????? Warehouse.class
      ???????? NanoHTTPD.java
      rmi/
      ???????? rmid.policy

    • step3)啟動RMI注冊表

    • step4)在rmi目錄中啟動 RMI激活守護程序

      rmid -J-Djava.security.policy=rmid.policy
      rmid程序監聽激活請求,并且激活另一個虛擬機中的對象。要啟動一個虛擬機,rmid 程序需要一定的權限。這些權限都在一個策略文件中說明了。使用-J, 可以傳遞一個選項給運行激活守護程序的虛擬機;

    • step5)在download 目錄中啟動NanoHTTPD Web 服務器;

    • step6) 從server目錄運行激活程序
      java -Djava.rmi.server.codebase=http://localhost:8080/ WarehouseActivator

    • step7) 從client目錄運行客戶端程序;

Attention) 上述結果是可以正確查找遠程對象,但是當調用Warehouse接口的實現類的getPrice 方法的時候,卻拋出了異常,搞了一下午,我確實無能為力了,先留在這里,以后有機會再來解決。。

  • 相關命令行指令如下:
rmid -J-Djava.security.policy=rmid.policy java com.corejava.chapter11.activation.download.NanoHTTPDMain java -Djava.rmi.server.codebase=http://localhost:8080/ com.corejava.chapter11.activation.server.WarehouseActivator

  • for full source code, please visit https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter11/activation

總結

以上是生活随笔為你收集整理的java分布式对象——远程方法中的参数和返回值+远程对象激活的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。