非直接緩沖區:
NIO通過通道連接磁盤文件與應用程序,通過緩沖區存取數據進行雙向的數據傳輸。物理磁盤的存取是操作系統進行管理的,與物理磁盤的數據操作需要經過內核地址空間;而我們的Java應用程序是通過JVM分配的緩沖空間。有點雷同於一個屬於核心態,一個屬於應用態的意思,而數據需要在內核地址空間和用戶地址空間,在操作系統和JVM之間進行數據的來回拷貝,無形中增加的中間環節使得效率與后面要提的之間緩沖區相比偏低。
直接緩沖區:
直接緩沖區則不再通過內核地址空間和用戶地址空間的緩存數據的復制傳遞,而是在物理內存中申請了一塊空間,這塊空間映射到內核地址空間和用戶地址空間,應用程序與磁盤之間的數據存取之間通過這塊直接申請的物理內存進行。
* 非直接緩沖區:通過 allocate() 方法分配緩沖區,將緩沖區建立在 JVM 的內存中
不安全。數據寫入物理內存緩沖區中,程序就喪失了對這些數據的管理,即什么時候這些數據被最終寫入從磁盤只能由操作系統來決定,應用程序無法再干涉。
* 直接緩沖區:通過 allocateDirect() 方法分配直接緩沖區,將緩沖區建立在物理內存中。可以提高效率。
直接字節緩沖區還可以通過FileChannel 的map() 方法將文件區域直接映射到內存中來創建。該方法返回MappedByteBuffer。Java 平台的實現有助於通過JNI 從本機代碼創建直接字節緩沖區。如果以上這些緩沖區中的某個緩沖區實例指的是不可訪問的內存區域,則試圖訪問該區域不會更改該緩沖區的內容,並且將會在訪問期間或稍后的某個時間導致拋出不確定的異常。
注:
字節緩沖區是直接緩沖區還是非直接緩沖區可通過調用其isDirect()方法來確定。提供此方法是為了能夠在性能關鍵型代碼中執行顯式緩沖區管理。
@Test public void test3(){ ByteBuffer dirBuf = ByteBuffer.allocateDirect(1024); if(dirBuf.isDirect()){ System.out.println("dirBuf 是直接緩沖區"); } else{ System.out.println("dirBuf 是非直接緩沖區"); } }