<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-128  評論-55  文章-5  trackbacks-0
     

    3.2.2 編譯源程序

    首先將兩個接口類Compute.classTask.class打成JAR包(compute.jar)傳到客戶端,或者向客戶端添加類路徑也行。這樣客戶端的類才能正確編譯。編譯過程不在詳述。

    需要被其他JVM動態(tài)加載的類要能夠通過網(wǎng)絡(luò)遠程訪問到,因此可以將它們放在一個Web服務(wù)器上,通過HTTP訪問。當然在本機上測試時也可以使用文件路徑,在此使用文件路徑,如file:/c:\home\user\public_html\classes/

    在本示例中注冊處需要動態(tài)從服務(wù)器端加載Compute.classTask.classComputeEngine_Stub.class

    存根類ComputeEngine_Stub是通過rmic命令生成的,在Dos窗口中,到ComputeEngine所在目錄(注意包路徑不包含在內(nèi)),運行

    rmic engine. ComputeEngine  即可自動生成ComputeEngine_Stub.class

    注意此例中存根類是必須的,因為我們使用的是public static RemoteStub exportObject(Remote obj) throws RemoteException方法導(dǎo)出遠程對象的,如果采用其它方法則可以不需要,臨時動態(tài)生成動態(tài)代理(JDK5.0版本后)

    服務(wù)器端需要動態(tài)從客戶端加載類Pi.class

    客戶端需要動態(tài)從服務(wù)器端加載類ComputeEngine_Stub.class,而Compute.classTask.class本地路徑中已有。

     

    3.2.3 運行源程序

    服務(wù)器端和客戶端在運行時都需要加載一個安全管理器,因此我們首先需要編寫兩個安全策略文件,允許訪問鏈接,這里使用最簡單的策略文件。

    grant {

        permission java.security.AllPermission;

    };

    其中客戶端策略文件client.policy和服務(wù)器端策略文件server.policy是相同的。

    1.         啟動注冊表

    Dos窗口中運行 rmiregistry,此命令是JDK提供的。

    2.         啟動服務(wù)器 (命令如下,Windows環(huán)境)

    java  -cp c:\home\ann\src;c:\home\ann\public_html\classes\compute.jar

    -Djava.rmi.server.codebase=file:/c:\home\ann\public_html\classes\compute.jar

        -Djava.rmi.server.hostname=localhost

        -Djava.security.policy=server.policy

         engine.ComputeEngine

    java.rmi.server.codebase 指定了一個地址,所需要的類定義可以從此地址下載。

    java.rmi.server.hostname 指定了存放遠程對象所對應(yīng)存根對象的主機名稱,客戶端在嘗試遠程對象方法調(diào)用時將用到此地址。

    java.security.policy 指定了所使用的安全策略文件。

    3.         啟動客戶端 (命令如下,Windows環(huán)境)

    java -cp c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar

         -Djava.rmi.server.codebase=file:/c:/home/jones/public_html/classes/

         -Djava.security.policy=client.policy

           client.ComputePi  localhost  45

    運行后會得到如下結(jié)果:

    3.141592653589793238462643383279502884197169399

    下圖描述了在程序執(zhí)行過程中rmiregistryComputeEngine serverComputePi client在哪里獲得類定義。

    3.3 類加載圖

    四、JDK5.0中的動態(tài)代理類

    4.1 JDK5.0RMI的新特性

    如果是在JDK5.0下運行程序會發(fā)現(xiàn)一些有意思的事情,如不生成遠程對象的存根文件,程序在運行時不會報錯。仍然可以正確的運行得到結(jié)果(這一點困擾我很長時間)。這是因為在JDK5.0以前的版本中,需要用rmic命令來為遠程對象生成靜態(tài)的代理類(包括存根和骨架類),而在JDK5.0中,RMI框架會在運行時自動為遠程對象生成動態(tài)代理類(包括存根和骨架類),從而更徹底的封裝的RMI框架的實現(xiàn)細節(jié),簡化了RMI框架的使用方式。

    JDK5.0中,如果無法加載遠程對象的stub類或?qū)⑾到y(tǒng)屬性 java.rmi.server.ignoreStubClasses 設(shè)置為 "true",并且我們使用除public static RemoteStub exportObject(Remote obj) throws RemoteException方法外的其它重載方法導(dǎo)出遠程對象時,程序運行時會構(gòu)造一個遠程對象的動態(tài)代理,是類java.lang.reflect.Proxy的一個實例,這樣在向注冊表注冊時傳遞給注冊表的是一個Proxy對象,而不是ComputeEngine_Stub對象,因為Proxy類在JDK中已有類定義,因此注冊處并不需要從服務(wù)器端加載Proxy類定義,但Compute類和Task類還是需要從服務(wù)器端加載的。

    同樣的道理,客戶端從注冊處獲得Proxy動態(tài)代理對象后,也不需要從服務(wù)器端獲得其類定義,從而客戶端不會從服務(wù)器端動態(tài)加載任何類定義,也就是說客戶端的安全管理器可以省略。但服務(wù)器端仍然需要動態(tài)從客戶端加載Pi類定義,從而服務(wù)器端的安全管理器不能省略。

    但是一旦生成了ComputeEngine_Stub存根類,那么程序就不會動態(tài)生成動態(tài)代理,那么整個運行過程就如3.2中所述。

    4.2 JDK5.0中的動態(tài)代理類

    動態(tài)代理類的字節(jié)碼在程序運行時由Java反射機制動態(tài)生成,無須程序員手工編寫它的源代碼。java.lang.reflect包中的Proxy類和InvocationHandler接口提供了生成動態(tài)代理類的能力。

    Proxy 提供用于創(chuàng)建動態(tài)代理類和實例的靜態(tài)方法,它還是由這些方法創(chuàng)建的所有動態(tài)代理類的超類。

    l         public static Class<?> getProxyClass(ClassLoader loader,Class<?>[] interfaces) throws IllegalArgumentException 靜態(tài)方法負責創(chuàng)建動態(tài)代理類,并向其提供類加載器和接口數(shù)組。該代理類將由指定的類加載器定義,并將實現(xiàn)提供的所有接口。如果類加載器已經(jīng)定義了具有相同排列接口的代理類,那么現(xiàn)有的代理類將被返回;否則,類加載器將動態(tài)生成并定義這些接口的代理類。

    l         public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException 靜態(tài)方法返回一個指定接口的代理類實例,該接口可以將方法調(diào)用指派到指定的調(diào)用處理程序。此方法相當于:Proxy.getProxyClass(loader, interfaces).getConstructor(new Class[] { InvocationHandler.class }).newInstance(new Object[] { handler });

    Proxy類的靜態(tài)方法創(chuàng)建的動態(tài)代理類(以下成為代理類)具有以下特點:

    l         代理類是公共的、最終的,和非抽象類型的。

    l         未指定代理類的非限定名稱。但是,以字符串 "$Proxy" 開頭的類名空間應(yīng)該為代理類保留。

    l         代理類繼承了 java.lang.reflect.Proxy類。

    l         代理類會按同一順序準確地實現(xiàn)其創(chuàng)建時指定的接口。

    l         如果代理類實現(xiàn)了非公共接口,那么它將在與該接口相同的包中定義。否則,代理類的包也是未指定的。注意,包密封將不阻止代理類在運行時在特定包中的成功定義,也不會阻止相同類加載器和帶有特定簽名的包所定義的類。

    l         由于代理類將實現(xiàn)所有在其創(chuàng)建時指定的接口,所以對其 Class 對象調(diào)用 getInterfaces 將返回一個包含相同接口列表的數(shù)組(按其創(chuàng)建時指定的順序),對其 Class 對象調(diào)用 getMethods 將返回一個包括這些接口中所有方法的 Method 對象的數(shù)組,并且調(diào)用 getMethod 將會在代理接口中找到期望的一些方法。

    l         Proxy類的isProxyClass(Class<?> cl) 靜態(tài)方法可用來判斷參數(shù)指定的類是否為動態(tài)代理類。只有由 Proxy.getProxyClass 返回的類,或由 Proxy.newProxyInstance 返回的對象的類才是動態(tài)代理類。

    l         代理類的 java.security.ProtectionDomain 與由引導(dǎo)類加載器(如 java.lang.Object)加載的系統(tǒng)類相同,原因是代理類的代碼由受信任的系統(tǒng)代碼生成。此保護域通常被授予 java.security.AllPermission

    l         每個代理類都有一個可以帶一個參數(shù)(接口 InvocationHandler 的實現(xiàn))的公共構(gòu)造方法,用于設(shè)置代理實例的調(diào)用處理程序。并非必須使用反射 API 才能訪問公共構(gòu)造方法,通過調(diào)用 Proxy.newInstance 方法(將調(diào)用 Proxy.getProxyClass 的操作和調(diào)用帶有調(diào)用處理程序的構(gòu)造方法結(jié)合在一起)也可以創(chuàng)建代理實例。

    l         每個代理類實例都和一個InvocationHandler實例關(guān)聯(lián)。Proxy類的getInvocationHandler(Object proxy)靜態(tài)方法返回與參數(shù)proxy指定的代理類實例所關(guān)聯(lián)的InvocationHandler對象。當調(diào)用代理類所實現(xiàn)接口的方法時,該方法會調(diào)用與它關(guān)聯(lián)的InvocationHandler對象的invoke()方法。

    InvacationHandler接口為方法調(diào)用接口,它聲明了負責調(diào)用任意一個方法的invoke()方法:Object invoke(Object proxy, Method method, Object[] args) throws Throwable,參數(shù)proxy指定動態(tài)代理類實例,參數(shù)method指定被調(diào)用的方法,參數(shù)args指定向被調(diào)用方法傳遞的參數(shù),invoke方法的返回值表示被調(diào)用方法的返回值。

     

    五、Java RMI總結(jié)

    5.1 Java RMI的優(yōu)點

    RMI機制給分布計算的系統(tǒng)設(shè)計、編程都帶來了極大的方便。只要按照RMI規(guī)則設(shè)計程序,可以不必再過問在RMI之下的網(wǎng)絡(luò)細節(jié)了,如:TCPSocket等等。任意兩臺計算機之間的通訊完全由RMI負責。調(diào)用遠程計算機上的對象就像本地對象一樣方便。

    1.         面向?qū)ο螅?/span>

    RMI可將完整的對象作為參數(shù)和返回值進行傳遞,而不僅僅是預(yù)定義的數(shù)據(jù)類型。也就是說,可以將類似Java哈西表這樣的復(fù)雜類型作為一個參數(shù)進行傳遞。

    2.         可移動屬性:

    RMI可將屬性從客戶機移動到服務(wù)器,或者從服務(wù)器移動到客戶機。

    3.         設(shè)計方式:

    對象傳遞功能使您可以在分布式計算中充分利用面向?qū)ο蠹夹g(shù)的強大功能,如二層和三層結(jié)構(gòu)系統(tǒng)。如果用戶能夠傳遞屬性,那么就可以在自己的解決方案中使用面向?qū)ο蟮脑O(shè)計方式。所有面向?qū)ο蟮脑O(shè)計方式無不依靠不同的屬性來發(fā)揮功能,如果不能傳遞完整的對象,包括實現(xiàn)和類型,就會失去設(shè)計方式上所提供的優(yōu)點。

    4.         安全性:

    RMI使用Java內(nèi)置的安全機制保證下載執(zhí)行程序時用戶系統(tǒng)的安全。RMI使用專門為保護系統(tǒng)免遭惡意小程序侵害而設(shè)計的安全管理程序。

    5.         便于編寫和使用

    RMI使得Java遠程服務(wù)程序和訪問這些服務(wù)程序的Java客戶程序的編寫工作變得輕松、簡單。遠程接口實際上就是Java接口。為了實現(xiàn)RMI的功能必須創(chuàng)建遠程對象任何可以被遠程調(diào)用的對象必須實現(xiàn)遠程接口。但遠程接口本身并不包含任何方法。因而需要創(chuàng)建一個新的接口來擴展遠程接口。新接口將包含所有可以遠程調(diào)用的方法。遠程對象必須實現(xiàn)這個新接口,由于新的接口擴展了遠程接口,實現(xiàn)了新接口,就滿足了遠程對象對實現(xiàn)遠程接口的要求,所實現(xiàn)的每個對象都將作為遠程對象引用。

    5.2 Java RMI的缺點

    RMI雖然編寫起來比較方便,但運行的效率較低,而且RMI局限于Java之間的通信,無法與其他的語言平臺進行通信。因此出現(xiàn)了RMI-IIOP技術(shù),RMI-IIOP綜合了RMI的簡單性和CORBA的多語言性(兼容性),其次RMI-IIOP克服了RMI只能用于Java的缺點和CORBA的復(fù)雜性(可以不用掌握IDL)。

     

    參考文獻

    [1] 李華琰、郭英奎 著:Java 中間件開發(fā)技術(shù) . 中國水利水電出版社,2005

    [2] David Reilly , Michael Reilly著,沈鳳等譯.Java網(wǎng)絡(luò)編程與分布式計算.北京:機械工業(yè)出版社,2003

    [3]孫衛(wèi)琴 著.Java網(wǎng)絡(luò)編程精解.北京:電子工業(yè)出版社,2007

    [4] Trail RMI (The Java™ Tutorials)2007

        http://java.sun.com/docs/books/tutorial/rmi/index.html

    [5] JDK5.0 中文文檔

     



    Author: orangelizq
    email: orangelizq@163.com

    歡迎大家訪問我的個人網(wǎng)站 萌萌的IT人
    posted on 2007-12-01 21:01 桔子汁 閱讀(1778) 評論(0)  編輯  收藏 所屬分類: J2SE
    主站蜘蛛池模板: 成年人视频在线观看免费| 亚洲免费人成在线视频观看| 亚洲成Av人片乱码色午夜| 国产精品无码亚洲一区二区三区| 一级毛片免费毛片一级毛片免费 | 歪歪漫画在线观看官网免费阅读| 亚洲乳大丰满中文字幕| 国产精品亚洲专区无码唯爱网| 在免费jizzjizz在线播| 日韩精品亚洲aⅴ在线影院| 亚洲精品无码久久久久秋霞| 67pao强力打造国产免费| 亚洲中文字幕无码永久在线| 激情小说亚洲图片| 日韩欧美一区二区三区免费观看 | 日批视频网址免费观看| 日本免费一本天堂在线| 亚洲制服丝袜精品久久| 亚欧免费无码aⅴ在线观看| 亚洲性猛交XXXX| 免费人成动漫在线播放r18| 午夜视频免费观看| 亚洲国产综合第一精品小说| 久久久久免费精品国产小说| 亚洲女久久久噜噜噜熟女| 一区二区三区免费精品视频 | 久久精品中文字幕免费| 亚洲熟妇中文字幕五十中出| 免费人成网站永久| 又爽又黄无遮挡高清免费视频| 亚洲日本va一区二区三区| 人禽杂交18禁网站免费| 亚洲精品视频在线免费| 一级毛片在线免费观看| 亚洲精品免费在线观看| 可以免费观看的毛片| 亚洲理论电影在线观看| 久青草视频97国内免费影视| 国产亚洲精品资在线| 国产大片免费天天看| 亚洲日韩中文字幕日韩在线|