本文目錄一覽:
Java 以下兩個要求 怎麼在Java中以程序的方式實現? (圍繞CORBA和IOR)
最近在看 JAVA NIO 的相關知識,了解一下IO的底層實現原理。
IO涉及到的底層的概念大致如下:
1) 緩衝區操作。2) 內核空間與用戶空間。3) 虛擬內存。4) 分頁技術。
一,虛擬存儲器
虛擬存儲器是硬件異常(缺頁異常)、硬件地址翻譯、主存、磁盤文件和內核軟件的完美交互,它為每個進程提供了一個大的、一致的和私有的地址空間。
虛擬存儲器的三大能力:①將主存看成是一個存儲在磁盤上的地址空間的高速緩存。②為每個進程提供了一個一致的地址空間。③保護每個進程的地址空間不被其他進程破壞。
虛擬內存的兩大好處:① 一個以上的虛擬地址可指向同一個物理內存地址。② 虛擬內存空間可大於實際可用的硬件內存。
二,用戶空間與內核空間
設虛擬地址為32位,那麼虛擬地址空間的範圍為0~4G。操作系統將這4G分為二部分,將最高的1G字節(虛擬地址範圍為:0xC0000000-0xFFFFFFFF)供內核使用,稱為內核空間。而將較低的3G字節供各個進程使用,稱為用戶空間。
每個進程可以通過系統調用進入內核,因為內核是由所有的進程共享的。對於每一個具體的進程,它看到的都是4G大小的虛擬地址空間,即相當於每個進程都擁有一個4G大小的虛擬地址空間。
三,IO操作
一般IO緩衝區操作:
1) 用戶進程使用read()系統調用,要求其用戶空間的緩衝區被填滿。
2) 內核向磁盤控制器硬件發命令,要求從磁盤讀入數據。
3) 磁盤控制器以DMA方式(數據不經過CPU)把數據複製到內核緩衝區。
4) 內核將數據從內核緩衝區複製到用戶進程發起read()調用時指定的用戶緩衝區。
從上圖可以看出:磁盤中的數據是先讀取到內核的緩衝區中。然後再從內核的緩衝區複製到用戶的緩衝區。為什麼會這樣呢?
因為用戶空間的進程是不能直接硬件的(操作磁盤控制器)。磁盤是基於塊存儲的硬件設備,它一次操作固定大小的塊,而用戶請求請求的可能是任意大小的數據塊。因此,將數據從磁盤傳遞到用戶空間,由內核負責數據的分解、再組合。
內存映射IO:就是復用一個以上的虛擬地址可以指向同一個物理內存地址。將內核空間的緩衝區地址(內核地址空間)映射到物理內存地址區域,將用戶空間的緩衝區地址(用戶地址空間)也映射到相同的物理內存地址區域。從而數據不需要從內核緩衝區映射的物理內存地址移動到用戶緩衝區映射的物理內存地址了。
要求:①用戶緩衝區與內核緩衝區必須使用相同的頁大小對齊。②緩衝區的大小必須是磁盤控制器塊大小(512字節磁盤扇區)的倍數—因為磁盤是基於塊存儲的硬件設備,一次只能操作固定大小的數據塊。
用戶緩衝區按頁對齊,會提高IO的效率—這也是為什麼在JAVA中new 一個字節數組時,指定的大小為2的倍數(4096)的原因吧。
四,JAVA中的IO,本質上是把數據移進或者移出緩衝區。
read()和write()系統調用完成的作用是:把內核緩衝區映射的物理內存空間中的數據 拷貝到 用戶緩衝區映射的物理內存空間中。
因此,當使用內存映射IO時,可視為:用戶進程直接把文件數據當作內存,也就不需要使用read()或write()系統調用了。
當發起一個read()系統調用時,根據待讀取的數據的位置生成一個虛擬地址(用戶進程使用的是虛擬地址),由MMU轉換成物理地址,若內核中沒有相應的數據,產生一個缺頁請求,內核負責頁面調入從而將數據從磁盤讀取到內核緩衝區映射的物理內存中。對用戶程序而言,這一切都是在不知不覺中進行。
總之,從根本上講數據從磁盤裝入內存是以頁為單位通過分頁技術裝入內存的。
五,JAVA NIO中的直接緩存和非直接緩存
直接緩存:不是分配於堆上的存儲,位於JVM之外,它不受JAVA的GC管理,相當於內核緩衝區。非直接緩存:建立在JAVA堆上的緩存,受JVM管理,相當於用戶緩衝區。
根據上面第三點,將直接緩存中的數據寫入通道的速度要快於非直接緩存。因為,連接到通道的另一端是文件(磁盤,FileChannel)或者網絡(Socket通道),這些都是某種形式上的硬件。那麼,對於非直接緩存而言,數據從緩衝區傳遞到硬件,要經過內核緩衝區中轉。而對於直接緩存而言,就不需要了,因為直接緩存已經直接映射到內核緩衝區了。
corba,java rmi和dcom/com的異同
CORBA:CORBA是Common Object Request Broker Architecture的縮寫,它是分布計算機技術的發展結果,CORBA技術的成功在於,它除了能夠解決由於多個系統層次上的異構帶來的“孤島”問題,還在理論和技術上擴展了客戶/服務器的模式,使系統具有良好的可伸縮性,便於系統的開發與升級,保護已有投資。
EJB容器是一個管理一個或多個EJB類/實例的抽象。它通過規範中定義的接口使EJB類訪問所需的服務。容器廠商也可以在容器或服務器中提供額外服務的接口。 現在沒有EJB服務器和EJB容器間接口的規範。因為目前容器通常由EJB服務器來提供,所以一旦接口標準化了,廠商就可能提供可以在任何兼容的EJB服務器上運行的容器。
DCOM:Microsoft的分布式COM(DCOM)擴展了組件對象模型技術(COM),使其能夠支持在局域網、廣域網甚至Internet上不同計算機的對象之間的通訊。使用DCOM,應用程序可以在位置上達到分布性,從而滿足客戶和應用的需求。
java中rmi和corba的區別
java中rmi和corba的區別:
1、定義接口:
rmi自己定義接口(interface)
corba生成idl代碼,然後使用idlj -fall name.idl生成接口和幾個類文件
2、啟動服務:
rmi啟動的是rmiregistry (port)默認1099
corba啟動的是tnameserv
3、實現的繼承類:
rmi extends UnicastRemoteObject
corba extends 運行idlj時 生成的_NameImplBase
4、實現類的rebind
rmi可以直接rebind 如:Naming.rebind(“rmi://localhost/meeting”,meetingserver);
corba需要先調用init()如:
ORB orb=ORB.init(avgs,null);
MOTDImpl impl=new MOTDImpl(motdFile);
orb.connect(impl);
org.omg.CORBA.Object objRef=
orb.resolve_initial_references(“NameService”);
NamingContext ncRef=NamingContextHelper.narrow(objRef);
NameComponent nc=new NameComponent(motdService,””);
NameComponent[] path=new NameComponent[]{nc};
ncRef.rebind(path,impl);
這裡corba就要麻煩很多了
5、客戶端調用corba的調用跟實現類的綁定差不多如:
ORB orb=ORB.init(avgs,null);
org.omg.CORBA.Object objRef=
orb.resolve_initial_references(“NameService”);
NamingContext ncRef=NamingContextHelper.narrow(objRef);
NameComponent nc=new NameComponent(“MessageOfTheDay”,””);
NameComponent path[]=new NameComponent[]{nc} ;
org.omg.CORBA.Object motdObj=ncRef.resolve(path);
MOTD motdRef=MOTDHelper.narrow(motdObj);
System.out.println(motdRef.getMOTD());
rmi只要lookup就可以了
總的來說其實rmi和corba都差不多,都是樁和框架,兩者相互競爭,但是在java中都可以相互調用。這歸功於rmi_iiop.
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/180217.html