鷹翔宇空

          學(xué)習(xí)和生活

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            110 Posts :: 141 Stories :: 315 Comments :: 1 Trackbacks
          引自:http://www.cnjsp.org/view.jsp?column=2&id=560
            
               EJB技術(shù)的基礎(chǔ)是另外兩種技術(shù):RMI-IIOP和JNDI。要想了解EJB,一定要先了解RMI-IIOP和JNDI。因此,我們?cè)诮榻BEJB細(xì)節(jié)之前,先了解這兩項(xiàng)技術(shù)。我們的介紹比較基本,因此大多數(shù)組織只要了解這些就已經(jīng)夠了。

          Java RMI-IIOP

              Java RMI-IIOP(Java Remote Method Invocation over the Internet Inter-ORB Protocol)是J2EE的網(wǎng)絡(luò)機(jī)制。Java RMI-IIOP允許你編寫分布式對(duì)象,使得對(duì)象的通信范圍能夠在內(nèi)存中,跨Java虛擬機(jī),跨物理設(shè)備。

          Remote Method Invocation

              RPC(remote procedure call)是一臺(tái)機(jī)器的進(jìn)程調(diào)用另一臺(tái)機(jī)器的進(jìn)程的過程。而remote method invocation則比RPC的概念更進(jìn)一步,允許分布式對(duì)象間的通信。RMI-IIOP允許調(diào)用遠(yuǎn)程對(duì)象的方法,而不僅僅是過程。這有利于面向?qū)ο缶幊獭ava RMI (Remote Method Invocation 遠(yuǎn)程方法調(diào)用)是用Java在JDK1.1中實(shí)現(xiàn)的,它大大增強(qiáng)了Java開發(fā)分布式應(yīng)用的能力。Java作為一種風(fēng)靡一時(shí)的網(wǎng)絡(luò)開發(fā)語言,其巨大的威力就體現(xiàn)在它強(qiáng)大的開發(fā)分布式網(wǎng)絡(luò)應(yīng)用的能力上,而RMI就是開發(fā)百分之百純Java的網(wǎng)絡(luò)分布式應(yīng)用系統(tǒng)的核心解決方案之一。其實(shí)它可以被看作是RPC的Java版本。但是傳統(tǒng)RPC并不能很好地應(yīng)用于分布式對(duì)象系統(tǒng)。而Java RMI 則支持存儲(chǔ)于不同地址空間的程序級(jí)對(duì)象之間彼此進(jìn)行通信,實(shí)現(xiàn)遠(yuǎn)程對(duì)象之間的無縫遠(yuǎn)程調(diào)用。

              remote method invocation決不簡(jiǎn)單,需要考慮幾個(gè)問題:

              marshalling和unmarshalling.在不同機(jī)器間通過網(wǎng)絡(luò)傳遞變量(包括Java基本類型和對(duì)象),如果目標(biāo)機(jī)器表示數(shù)據(jù)的方式和原機(jī)器不同該怎么辦?例如二進(jìn)制庫不同。因此marshalling和unmarshalling就是傳遞變量的過程。

              變量傳遞方法.變量有兩種傳遞方法:pass-by-value和pass-by-reference。對(duì)于前者,你的目標(biāo)方法只需使用一份copy,但對(duì)于后者,遠(yuǎn)程方法對(duì)變量的任何修改都會(huì)影響到源數(shù)據(jù)。

              網(wǎng)絡(luò)和機(jī)器的不穩(wěn)定.需要有一種機(jī)制保證一個(gè)JVM崩潰之后,不會(huì)影響系統(tǒng)的正常運(yùn)作。

              在 Java 分布式對(duì)象模型中,remote object 是這樣一種對(duì)象:它的方法可以從其它 Java 虛擬機(jī)(可能在不同的主機(jī)上)中調(diào)用。該類型的對(duì)象由一種或多種 remote interfaces(它是聲明遠(yuǎn)程對(duì)象方法的 Java 接口)描述。遠(yuǎn)程方法調(diào)用 (RMI) 就是調(diào)用遠(yuǎn)程對(duì)象上遠(yuǎn)程接口的方法的動(dòng)作。更為重要的是,遠(yuǎn)程對(duì)象的方法調(diào)用與本地對(duì)象的方法調(diào)用語法相同。

          Remote Interface

              RMI-IIOP遵循了接口和實(shí)現(xiàn)的原則。你寫的所有網(wǎng)絡(luò)代碼都是應(yīng)用于接口,而不是實(shí)現(xiàn)。實(shí)際上,你必須使用RMI-IIOP中的范例,沒有其它的選擇。直接在你的對(duì)象實(shí)現(xiàn)上執(zhí)行遠(yuǎn)程調(diào)用是不可能的,你只能在對(duì)象類的接口上單獨(dú)進(jìn)行這一操作。

              所以我們?cè)谑褂肦MI-IIOP時(shí),你必須建立一個(gè)客戶接口,叫做remote interface。這個(gè)遠(yuǎn)程接口應(yīng)該擴(kuò)展java.rmi.Remote接口。

          Remote Object Implementation

              遠(yuǎn)程對(duì)象和客戶機(jī)的物理位置并不是很重要。可以運(yùn)行在同一地址空間或是跨Internet運(yùn)行。

              為了使對(duì)象成為一個(gè)遠(yuǎn)程對(duì)象,你需要執(zhí)行一下步驟:

              繼承javax.rmi.PortableRemoteObject。PortableRemoteObject是進(jìn)行遠(yuǎn)程調(diào)用的基類,當(dāng)你的遠(yuǎn)程對(duì)象調(diào)用構(gòu)造器時(shí),PortableRemoteObject對(duì)象的構(gòu)造器也會(huì)自動(dòng)被調(diào)用。

              不繼承javax.rmi.PortableRemoteObject。如果你的遠(yuǎn)程對(duì)象需要繼承其它的類,而Java不允許多重繼承,因此你不能繼承PortableRemoteObject。這時(shí),你需要手動(dòng)調(diào)用javax.rmi.PortableRemoteObject.exportObject()。

          Stub和Skeletons

              我們來看看在RMI-IIOP背后隱藏的網(wǎng)絡(luò)架構(gòu)。RMI-IIOP的一個(gè)好處就是你可以不用管你要調(diào)用的對(duì)象是本地的還是遠(yuǎn)程的。這就叫做local/remote transparency。

              RMI應(yīng)用程序通常包括兩個(gè)獨(dú)立的程序:服務(wù)器程序和客戶機(jī)程序。典型的服務(wù)器應(yīng)用程序?qū)?chuàng)建多個(gè)遠(yuǎn)程對(duì)象,使這些遠(yuǎn)程對(duì)象能夠被引用,然后等待客戶機(jī)調(diào)用這些遠(yuǎn)程對(duì)象的方法。而典型的客戶機(jī)程序則從服務(wù)器中得到一個(gè)或多個(gè)遠(yuǎn)程對(duì)象的引用,然后調(diào)用遠(yuǎn)程對(duì)象的方法。RMI為服務(wù)器和客戶機(jī)進(jìn)行通信和信息傳遞提供了一種機(jī)制。






              在與遠(yuǎn)程對(duì)象的通信過程中,RMI使用標(biāo)準(zhǔn)機(jī)制:stub和skeleton。遠(yuǎn)程對(duì)象的stub擔(dān)當(dāng)遠(yuǎn)程對(duì)象的客戶本地代表或代理人角色。調(diào)用程序?qū)⒄{(diào)用本地stub的方法,而本地stub將負(fù)責(zé)執(zhí)行對(duì)遠(yuǎn)程對(duì)象的方法調(diào)用。在RMI中,遠(yuǎn)程對(duì)象的stub與該遠(yuǎn)程對(duì)象所實(shí)現(xiàn)的遠(yuǎn)程接口集相同。調(diào)用stub的方法時(shí)將執(zhí)行下列操作:(1) 初始化與包含遠(yuǎn)程對(duì)象的遠(yuǎn)程虛擬機(jī)的連接;(2) 對(duì)遠(yuǎn)程虛擬機(jī)的參數(shù)進(jìn)行編組(寫入并傳輸);(3) 等待方法調(diào)用結(jié)果;(4) 解編(讀取)返回值或返回的異常;(5) 將值返回給調(diào)用程序。為了向調(diào)用程序展示比較簡(jiǎn)單的調(diào)用機(jī)制,stub將參數(shù)的序列化和網(wǎng)絡(luò)級(jí)通信等細(xì)節(jié)隱藏了起來。在遠(yuǎn)程虛擬機(jī)中,每個(gè)遠(yuǎn)程對(duì)象都可以有相應(yīng)的skeleton(在JDK1.2環(huán)境中無需使用skeleton)。Skeleton負(fù)責(zé)將調(diào)用分配給實(shí)際的遠(yuǎn)程對(duì)象實(shí)現(xiàn)。它在接收方法調(diào)用時(shí)執(zhí)行下列操作:(1) 解編(讀取)遠(yuǎn)程方法的參數(shù);(2) 調(diào)用實(shí)際遠(yuǎn)程對(duì)象實(shí)現(xiàn)上的方法;(3) 將結(jié)果(返回值或異常)編組(寫入并傳輸)給調(diào)用程序。stub和skeleton由rmic編譯器生成。

              要實(shí)現(xiàn)local/remote transparency可沒有那么簡(jiǎn)單。為了屏蔽你調(diào)用的是遠(yuǎn)端主機(jī)上的對(duì)象,RMI-IIOP需要模擬一個(gè)本地對(duì)象供你調(diào)用。這個(gè)本地對(duì)象叫做stub。它負(fù)責(zé)接受本地的方法調(diào)用請(qǐng)求,把這些請(qǐng)求委托給真正實(shí)現(xiàn)它們的對(duì)象(可以通過網(wǎng)絡(luò)定位)。這樣就使得遠(yuǎn)程調(diào)用看起來就和本地調(diào)用一樣。

              利用RMI編寫分布式對(duì)象應(yīng)用程序需要完成以下工作:(1) 定位遠(yuǎn)程對(duì)象。應(yīng)用程序可使用兩種機(jī)制中的一種得到對(duì)遠(yuǎn)程對(duì)象的引用。它既可用RMI的簡(jiǎn)單命名工具rmiregistry來注冊(cè)它的遠(yuǎn)程對(duì)象,也可以將遠(yuǎn)程對(duì)象引用作為常規(guī)操作的一部分來進(jìn)行傳遞和返回。(2)與遠(yuǎn)程對(duì)象通信。遠(yuǎn)程對(duì)象間通信的細(xì)節(jié)由RMI處理,對(duì)于程序員來說,遠(yuǎn)程通信看起來就像標(biāo)準(zhǔn)的Java方法調(diào)用。(3)給作為參數(shù)或返回值傳遞的對(duì)象加載類字節(jié)碼。因?yàn)镽MI允許調(diào)用程序?qū)⒓僇ava對(duì)象傳給遠(yuǎn)程對(duì)象,所以,RMI將提供必要的機(jī)制,既可以加載對(duì)象的代碼又可以傳輸對(duì)象的數(shù)據(jù)。在RMI分布式應(yīng)用程序運(yùn)行時(shí),服務(wù)器調(diào)用注冊(cè)服務(wù)程序以使名字與遠(yuǎn)程對(duì)象相關(guān)聯(lián)。客戶機(jī)在服務(wù)器上的注冊(cè)服務(wù)程序中用遠(yuǎn)程對(duì)象的名字查找該遠(yuǎn)程對(duì)象,然后調(diào)用它的方法。

              定位遠(yuǎn)程對(duì)象。應(yīng)用程序可使用兩種機(jī)制中的一種得到對(duì)遠(yuǎn)程對(duì)象的引用。它既可用 RMI 的簡(jiǎn)單命名工具 rmiregistry 來注冊(cè)它的遠(yuǎn)程對(duì)象;也可將遠(yuǎn)程對(duì)象引用作為常規(guī)操作的一部分來進(jìn)行傳遞和返回。 

              與遠(yuǎn)程對(duì)象通訊。遠(yuǎn)程對(duì)象間通訊的細(xì)節(jié)由 RMI 處理;對(duì)于程序員來說,遠(yuǎn)程通訊看起來就象標(biāo)準(zhǔn)的 Java 方法調(diào)用。給作為參數(shù)或返回值傳遞的對(duì)象加載類字節(jié)碼因?yàn)?nbsp;RMI允許調(diào)用程序?qū)⒓?nbsp;Java 對(duì)象傳給遠(yuǎn)程對(duì)象,所以 RMI 將提供必要的機(jī)制,既可以加載對(duì)象的代碼又可以傳輸對(duì)象的數(shù)據(jù)。服務(wù)器調(diào)用注冊(cè)服務(wù)程序以使名字與遠(yuǎn)程對(duì)象相關(guān)聯(lián)。客戶機(jī)在服務(wù)器注冊(cè)服務(wù)程序中用遠(yuǎn)程對(duì)象的名字查找該遠(yuǎn)程對(duì)象,然后調(diào)用它的方法。RMI 能用 Java系統(tǒng)支持的任何 URL 協(xié)議(例如 HTTP、FTP、file 等)加載類字節(jié)碼。

              stub只是解決了一半的問題。我們還希望遠(yuǎn)程對(duì)象也不用考慮網(wǎng)絡(luò)問題。因此遠(yuǎn)程對(duì)象也需要一個(gè)本地的skeleton來接受調(diào)用。skeleton接受網(wǎng)絡(luò)調(diào)用并把調(diào)用委托給遠(yuǎn)程對(duì)象實(shí)現(xiàn)。

              你的J2EE服務(wù)器應(yīng)當(dāng)提供一種方法來產(chǎn)生必須的stub和skeleton,以減輕你的對(duì)網(wǎng)絡(luò)問題考慮的負(fù)擔(dān)。典型的是通過命令行工具來完成,例如sun的J2EE參考實(shí)現(xiàn)包就使用了一個(gè)名為rmic(RMI compiler)的工具來產(chǎn)生stub和skeleton類。你應(yīng)當(dāng)把stub部署在客戶機(jī)上,并把skeleton部署在服務(wù)器上。

          對(duì)象序列化和變量傳遞

              在RMI分布式應(yīng)用系統(tǒng)中,服務(wù)器與客戶機(jī)之間傳遞的Java對(duì)象必須是可序列化的對(duì)象。不可序列化的對(duì)象不能在對(duì)象流中進(jìn)行傳遞。對(duì)象序列化擴(kuò)展了核心Java輸入/輸出類,同時(shí)也支持對(duì)象。對(duì)象序列化支持把對(duì)象編碼以及將通過它們可訪問到的對(duì)象編碼變成字節(jié)流;同時(shí),它也支持流中對(duì)象圖形的互補(bǔ)重構(gòu)造。序列化用于輕型持久性和借助于套接字或遠(yuǎn)程方法調(diào)用(RMI)進(jìn)行的通信。序列化中現(xiàn)在包括一個(gè) API(Application Programming Interface,應(yīng)用程序接口),允許獨(dú)立于類的域指定對(duì)象的序列化數(shù)據(jù),并允許使用現(xiàn)有協(xié)議將序列化數(shù)據(jù)域?qū)懭肓髦谢驈牧髦凶x取,以確保與缺省讀寫機(jī)制的兼容性。

              為編寫應(yīng)用程序,除多數(shù)瞬態(tài)應(yīng)用程序外,都必須具備存儲(chǔ)和檢索 Java對(duì)象的能力。以序列化方式存儲(chǔ)和檢索對(duì)象的關(guān)鍵在于提供重新構(gòu)造該對(duì)象所需的足夠?qū)ο鬆顟B(tài)。存儲(chǔ)到流的對(duì)象可能會(huì)支持 Serializable(可序列化)或 Externalizable(可外部化)接口。對(duì)于Java對(duì)象,序列化形式必須能標(biāo)識(shí)和校驗(yàn)存儲(chǔ)其內(nèi)容的對(duì)象所屬的 Java類,并且將該內(nèi)容還原為新的實(shí)例。對(duì)于可序列化對(duì)象,流將提供足夠的信息將流的域還原為類的兼容版本。對(duì)于可外部化對(duì)象,類將全權(quán)負(fù)責(zé)其內(nèi)容的外部格式。序列化 Java 對(duì)象的目的是:提供一種簡(jiǎn)單但可擴(kuò)充的機(jī)制,以序列化方式維護(hù) Java對(duì)象的類型及安全屬性;具有支持編組和解編的擴(kuò)展能力以滿足遠(yuǎn)程對(duì)象的需要;具有可擴(kuò)展性以支持 Java 對(duì)象的簡(jiǎn)單持久性;只有在自定義時(shí),才需對(duì)每個(gè)類提供序列化自實(shí)現(xiàn);允許對(duì)象定義其外部格式。

          java.rmi.Remote 接口 

              在 RMI 中,遠(yuǎn)程接口是聲明了可從遠(yuǎn)程 Java 虛擬機(jī)中調(diào)用的方法集。遠(yuǎn)程接 
          口必須滿足下列要求: 

              遠(yuǎn)程接口至少必須直接或間接擴(kuò)展 java.rmi.Remote 接口。 
              遠(yuǎn)程接口中的方法聲明必須滿足下列遠(yuǎn)程方法聲明的要求: 
              遠(yuǎn)程方法聲明在其 throws 子句中除了要包含與應(yīng)用程序有關(guān)的異常(注意與應(yīng)用程序有關(guān)的異常無需擴(kuò)展 java.rmi.RemoteException )之外,還必須包括 java.rmi.RemoteException 異常(或它的超類,例如java.io.IOException 或 java.lang.Exception )。 
              遠(yuǎn)程方法聲明中,作為參數(shù)或返回值聲明的(在參數(shù)表中直接聲明或嵌入到參數(shù)的非遠(yuǎn)程對(duì)象中)遠(yuǎn)程對(duì)象必須聲明為遠(yuǎn)程接口,而非該接口的實(shí)現(xiàn)類。

              java.rmi.Remote 接口是一個(gè)不定義方法的標(biāo)記接口: 

          public interface Remote 

              遠(yuǎn)程接口必須至少擴(kuò)展 java.rmi.Remote 接口(或其它擴(kuò)展java.rmi.Remote 的遠(yuǎn)程接口)。然而,遠(yuǎn)程接口在下列情況中可以擴(kuò)展非遠(yuǎn)程接口: 

              遠(yuǎn)程接口也可擴(kuò)展其它非遠(yuǎn)程接口,只要被擴(kuò)展接口的所有方法(如果有)滿足遠(yuǎn)程方法聲明的要求。 
              例如,下面的接口 BankAccount 即為訪問銀行帳戶定義了一個(gè)遠(yuǎn)程接口。它包含往帳戶存款、使帳戶收支平衡和從帳戶取款的遠(yuǎn)程方法: 

          public interface BankAccount extends java.rmi.Remote 

          public void deposit(float amount) 
          throws java.rmi.RemoteException; 
          public void withdraw(float amount) 
          throws OverdrawnException, java.rmi.RemoteException; 
          public float getBalance() 
          throws java.rmi.RemoteException; 


              下例說明了有效的遠(yuǎn)程接口 Beta。它擴(kuò)展非遠(yuǎn)程接口 Alpha(有遠(yuǎn)程方法)和接口 java.rmi.Remote: 
          public interface Alpha 

          public final String okay = "constants are okay too"; 
          public Object foo(Object obj) 
          throws java.rmi.RemoteException; 
          public void bar() throws java.io.IOException; 
          public int baz() throws java.lang.Exception; 


          public interface Beta extends Alpha, java.rmi.Remote { 
          public void ping() throws java.rmi.RemoteException; 


          RemoteException 類 

              java.rmi.RemoteException 類是在遠(yuǎn)程方法調(diào)用期間由 RMI 運(yùn)行時(shí)所拋出的異常的超類。為確保使用 RMI 系統(tǒng)的應(yīng)用程序的健壯性,遠(yuǎn)程接口中聲明的遠(yuǎn)程方法在其 throws 子句中必須指定 java.rmi.RemoteException(或它的超類,例如 java.io.IOException 或 java.lang.Exception)。 

          當(dāng)遠(yuǎn)程方法調(diào)用由于某種原因失敗時(shí),將拋出 java.rmi.RemoteException 異常。遠(yuǎn)程方法調(diào)用失敗的原因包括: 

              通訊失敗(遠(yuǎn)程服務(wù)器不可達(dá)或拒絕連接;連接被服務(wù)器關(guān)閉等。) 
              參數(shù)或返回值傳輸或讀取時(shí)失敗 
              協(xié)議錯(cuò)誤 

              RemoteException 類是一個(gè)已檢驗(yàn)的異常(必須由遠(yuǎn)程方法的調(diào)用程序處理并經(jīng)編譯器檢驗(yàn)的異常),而不是 RuntimeException。 

          RemoteObject 類及其子類 

              RMI 服務(wù)器函數(shù)由 java.rmi.server.RemoteObject 及其子類java.rmi.server.RemoteServer、java.rmi.server.UnicastRemoteObject和 java.rmi.activation.Activatable 提供。 

              java.rmi.server.RemoteObject 為對(duì)遠(yuǎn)程對(duì)象敏感的 java.lang.Object方法、hashCode、 equals 和 toString 提供實(shí)現(xiàn)。 

              創(chuàng)建遠(yuǎn)程對(duì)象并將其導(dǎo)出(使它們可為遠(yuǎn)程客戶機(jī)利用)所需的方法由類UnicastRemoteObject 和 Activatable 提供。子類可以識(shí)別遠(yuǎn)程引用的語義,例如服務(wù)器是簡(jiǎn)單的遠(yuǎn)程對(duì)象還是可激活的遠(yuǎn)程對(duì)象(調(diào)用時(shí)將執(zhí)行的遠(yuǎn)程對(duì)象)。java.rmi.server.UnicastRemoteObject 類定義了單體(單路傳送)遠(yuǎn)程對(duì)
          象,其引用只有在服務(wù)器進(jìn)程活著時(shí)才有效。類 java.rmi.activation.Activatable 是抽象類,它定義的 activatable遠(yuǎn)程對(duì)象在其遠(yuǎn)程方法被調(diào)用時(shí)開始執(zhí)行并在必要時(shí)自己關(guān)閉。 

          實(shí)現(xiàn)遠(yuǎn)程接口 

              實(shí)現(xiàn)遠(yuǎn)程接口的類的一般規(guī)則如下: 

              該類通常擴(kuò)展 java.rmi.server.UnicastRemoteObject,因而將繼承類java.rmi.server.RemoteObject 和java.rmi.server.RemoteServer 提供的遠(yuǎn)程行為。
              該類能實(shí)現(xiàn)任意多的遠(yuǎn)程接口。 
              該類能擴(kuò)展其它遠(yuǎn)程實(shí)現(xiàn)類。 
              該類能定義遠(yuǎn)程接口中不出現(xiàn)的方法,但這些方法只能在本地使用而不能在遠(yuǎn)程使用。 

              例如,下面的類 BankAcctImpl 實(shí)現(xiàn) BankAccount 遠(yuǎn)程接口并擴(kuò)展java.rmi.server.UnicastRemoteObject 類: 

          package mypackage; 

          import java.rmi.RemoteException; 
          import java.rmi.server.UnicastRemoteObject; 

          public class BankAccountImpl extends UnicastRemoteObject implements 
          BankAccount 


          private float balance = 0.0; 

          public BankAccountImpl(float initialBalance) 
          throws RemoteException 

          balance = initialBalance; 


          public void deposit(float amount) throws RemoteException 

          ... 


          public void withdraw(float amount) throws OverdrawnException, 
          RemoteException 

          ... 


          public float getBalance() throws RemoteException 

          ... 




              注意:必要時(shí),實(shí)現(xiàn)遠(yuǎn)程接口的類能擴(kuò)展除java.rmi.server.UnicastRemoteObject 類以外的其它一些類。但實(shí)現(xiàn)類此時(shí)必須承擔(dān)起一定的責(zé)任,即導(dǎo)出對(duì)象(由 UnicastRemoteObject 構(gòu)造函數(shù)負(fù)責(zé))和實(shí)現(xiàn)從 java.lang.Object 類繼承的 hashCode、 equals 和toString 方法的正確遠(yuǎn)程語義(如果需要)。 


          遠(yuǎn)程方法調(diào)用中的參數(shù)傳遞 

              傳給遠(yuǎn)程對(duì)象的參數(shù)或源于它的返回值可以是任意可序列化的 Java 對(duì)象。這包括 Java 基本類型, 遠(yuǎn)程?Java 對(duì)象和實(shí)現(xiàn) java.io.Serializable 接口的非遠(yuǎn)程 Java 對(duì)象。有關(guān)如何使類序列化的詳細(xì)信息,參見 Java“對(duì)象序列化規(guī)范”。本地得不到的作為參數(shù)或返回值的類,可通過 RMI 系統(tǒng)進(jìn)行動(dòng)態(tài)下載。 

          傳遞非遠(yuǎn)程對(duì)象 

              非遠(yuǎn)程對(duì)象將作為遠(yuǎn)程方法調(diào)用的參數(shù)傳遞或作為遠(yuǎn)程方法調(diào)用的結(jié)果返回時(shí),是通過復(fù)制傳遞的;也就是使用 Java 對(duì)象序列化機(jī)制將該對(duì)象序列化。因此,在遠(yuǎn)程對(duì)象調(diào)用過程中,當(dāng)非遠(yuǎn)程對(duì)象作為參數(shù)或返回值傳遞時(shí),非遠(yuǎn)程對(duì)象的內(nèi)容在調(diào)用遠(yuǎn)程對(duì)象之前將被復(fù)制。從遠(yuǎn)程方法調(diào)用返回非遠(yuǎn)程對(duì)象時(shí),將在調(diào)用的虛擬機(jī)中創(chuàng)建新對(duì)象。 

          傳遞遠(yuǎn)程對(duì)象 

              當(dāng)將遠(yuǎn)程對(duì)象作為遠(yuǎn)程方法調(diào)用的參數(shù)或返回值傳遞時(shí),遠(yuǎn)程對(duì)象的 stub 程序即被傳遞出去。作為參數(shù)傳遞的遠(yuǎn)程對(duì)象僅能實(shí)現(xiàn)遠(yuǎn)程接口。 

          引用的完整性 

              如果一個(gè)對(duì)象的兩個(gè)引用在單個(gè)遠(yuǎn)程方法調(diào)用中以參數(shù)形式(或返回值形式)從一個(gè)虛擬機(jī)傳到另一個(gè)虛擬機(jī)中,并且它們?cè)诎l(fā)送虛擬機(jī)中指向同一對(duì)象,則兩個(gè)引用在接收虛擬機(jī)中將指向該對(duì)象的同一副本。進(jìn)一步說就是:在單個(gè)遠(yuǎn)程方法調(diào)用中,RMI 系統(tǒng)將在作為調(diào)用參數(shù)或返回值傳遞的對(duì)象中保持引用的完整性。 

          類注解 

              當(dāng)對(duì)象在遠(yuǎn)程調(diào)用中被從一個(gè)虛擬機(jī)發(fā)送到另一個(gè)虛擬機(jī)中時(shí),RMI 系統(tǒng)在調(diào)用流中用類的信息 (URL) 給類描述符加注解,以便該類能在接收器上加載。在遠(yuǎn)程方法調(diào)用期間,調(diào)用可隨時(shí)下載類。 

          參數(shù)傳輸 

              為將 RMI 調(diào)用的參數(shù)序列化到遠(yuǎn)程調(diào)用的目的文件里,需要將該參數(shù)寫入作為java.io.ObjectOutputStream 類的子類的流中。ObjectOutputStream 子類將覆蓋 replaceObject 方法,目的是用其相應(yīng)的 stub 類取代每個(gè)遠(yuǎn)程對(duì)象。對(duì)象參數(shù)將通過 ObjectOutputStream 的 writeObject 方法寫入流中。而ObjectOutputStream 則通過 writeObject 方法為每個(gè)寫入流中的對(duì)象(包含所寫對(duì)象所引用的對(duì)象)調(diào)用 replaceObject 方法。RMIObjectOutputStream子類的 replaceObject 方法返回下列值: 
          如果傳給 replaceObject 的對(duì)象是 java.rmi.Remote 的實(shí)例,則返回遠(yuǎn)程對(duì)象的 stub 程序。遠(yuǎn)程對(duì)象的 stub 程序通過對(duì)java.rmi.server.RemoteObject.toStub方法的調(diào)用而獲得。如果傳給 replaceObject 的對(duì)象不是 java.rmi.Remote 的實(shí)例,則只返回該對(duì)象。 

              RMI 的 ObjectOutputStream 子類也實(shí)現(xiàn) annotateClass 方法,該方法用類的位置注解調(diào)用流以便能在接收器中下載該類。有關(guān)如何使用 annotateClass的詳細(xì)信息,參見“動(dòng)態(tài)類加載”一節(jié)。因?yàn)閰?shù)只寫入一個(gè) ObjectOutputStream,所以指向調(diào)用程序同一對(duì)象的引用將在接收器那里指向該對(duì)象的同一副本。在接收器上,參數(shù)將被單個(gè)ObjectInputStream 所讀取。 

              用于寫對(duì)象的 ObjectOutputStream(類似的還有用于讀對(duì)象的ObjectInputStream )的所有其它缺省行為將保留在參數(shù)傳遞中。例如,寫對(duì)象時(shí)對(duì) writeReplace 的調(diào)用及讀對(duì)象時(shí)對(duì) readResolve 的調(diào)用就是由 RMI的參數(shù)編組與解編流完成的。 

              與上述 RMI 參數(shù)傳遞方式類似,返回值(或異常)將被寫入ObjectOutputStream的子類并和參數(shù)傳輸?shù)奶娲袨橄嗤?nbsp;

          定位遠(yuǎn)程對(duì)象 

              我們專門提供了一種簡(jiǎn)單的引導(dǎo)名字服務(wù)器,用于存儲(chǔ)對(duì)遠(yuǎn)程對(duì)象的已命名引用。使用類 java.rmi.Naming 的基于 URL 的方法可以存儲(chǔ)遠(yuǎn)程對(duì)象引用。客戶機(jī)要調(diào)用遠(yuǎn)程對(duì)象的方法,則必須首先得到該對(duì)象的引用。對(duì)遠(yuǎn)程對(duì)象的引用通常是在方法調(diào)用中以返回值的形式取得。RMI 系統(tǒng)提供一種簡(jiǎn)單的引導(dǎo)名字服務(wù)器,通過它得到給定主機(jī)上的遠(yuǎn)程對(duì)象。java.rmi.Naming 類提供基于統(tǒng)一資源定位符 (URL) 的方法,用來綁定、再綁定、解開和列出位于某一主機(jī)及端口上的名字-對(duì)象對(duì)。 
           
          posted on 2006-01-19 11:33 TrampEagle 閱讀(243) 評(píng)論(0)  編輯  收藏 所屬分類: EJB

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 历史| 青河县| 涞源县| 三都| 昌都县| 都安| 邵阳市| 清镇市| 恩平市| SHOW| 盐城市| 山东| 荔波县| 礼泉县| 周宁县| 霍林郭勒市| 确山县| 芜湖市| 汉阴县| 毕节市| 罗源县| 寿阳县| 永城市| 芜湖市| 文昌市| 体育| 德安县| 思茅市| 天津市| 武冈市| 贵南县| 乌拉特后旗| 武隆县| 玉门市| 车险| 华池县| 宾川县| 奉节县| 盐津县| 上蔡县| 石家庄市|