- 直接緩沖區與非直接緩沖區的概念:
1)非直接緩沖區:通過
static ByteBuffer allocate(int capacity)
創建的緩沖區,在JVM中內存中創建,在每次調用基礎操作系統的一個本機IO之前或者之后,虛擬機都會將緩沖區的內容復制到中間緩沖區(或者從中間緩沖區復制內容),緩沖區的內容駐留在JVM內,因此銷毀容易,但是占用JVM內存開銷,處理過程中有復制操作。
非直接緩沖區寫入步驟:
1.創建一個臨時的直接ByteBuffer對象。
2.將非直接緩沖區的內容復制到臨時緩沖中。
3.使用臨時緩沖區執行低層次I/O操作。
4.臨時緩沖區對象離開作用域,並最終成為被回收的無用數據。
2)直接緩沖區 :通過
static ByteBuffer allocateDirect(int capacity)
創建的緩沖區,在JVM內存外開辟內存,在每次調用基礎操作系統的一個本機IO之前或者之后,虛擬機都會避免將緩沖區的內容復制到中間緩沖區(或者從中間緩沖區復制內容),緩沖區的內容駐留在物理內存內,會少一次復制過程,如果需要循環使用緩沖區,用直接緩沖區可以很大地提高性能。雖然直接緩沖區使JVM可以進行高效的I/O操作,但它使用的內存是操作系統分配的,繞過了JVM堆棧,建立和銷毀比堆棧上的緩沖區要更大的開銷。
- 直接緩沖區與非直接緩沖區的區別:
- 字節緩沖區要么是直接的,要么是非直接的。如果為直接字節緩沖區,則 Java 虛擬機會盡最大努力直接在此緩沖區上執行本機 I/O 操作。也就是說,在每次調用基礎操作系統的一個本機 I/O 操作之前(或之后),虛擬機都會盡量避免將緩沖區的內容復制到中間緩沖區中(或從中間緩沖區中復制內容)。
- 直接字節緩沖區可以通過調用此類的 allocateDirect() 工廠方法來創建。此方法返回的緩沖區進行分配和取消分配所需成本通常高於非直接緩沖區。直接緩沖區的內容可以駐留在常規的垃圾回收堆之外,因此,它們對應用程序的內存需求量造成的影響可能並不明顯。所以,建議將直接緩沖區主要分配給那些易受基礎系統的本機 I/O 操作影響的大型、持久的緩沖區。一般情況下,最好僅在直接緩沖區能在程序性能方面帶來明顯好處時分配它們。
- 直接字節緩沖區還可以通過 FileChannel 的 map() 方法 將文件區域直接映射到內存中來創建。該方法返回MappedByteBuffer 。 Java 平台的實現有助於通過 JNI 從本機代碼創建直接字節緩沖區。如果以上這些緩沖區中的某個緩沖區實例指的是不可訪問的內存區域,則試圖訪問該區域不會更改該緩沖區的內容,並且將會在訪問期間或稍后的某個時間導致拋出不確定的異常。
- 字節緩沖區是直接緩沖區還是非直接緩沖區可通過調用其 isDirect() 方法來確定。提供此方法是為了能夠在性能關鍵型代碼中執行顯式緩沖區管理。
- 直接緩沖區與非直接緩沖區區別圖形示意: