網絡資料的基本機關總是位元組。Java NIO 提供了 ByteBuffer 作為它的位元組容器,但是這個類使用起來過于複雜,而且也有些繁瑣。Netty 的 ByteBuffer 替代品是 ByteBuf,一個強大的實作,既解決了 JDK API 的局限性,又為網絡應用程式的開發者提供了更好的 API
ByteBuf優勢
- 它可以被使用者自定義的緩沖區類型擴充
- 通過内置的複合緩沖區類型實作了透明的零拷貝
- 容量可以按需增長
- 在讀和寫這兩種模式之間切換不需要調用 ByteBuffer 的 flip()方法
- 讀和寫使用了不同的索引
- 支援方法的鍊式調用
- 支援引用計數
- 支援池化
ByteBuf實作原理

如圖ByteBuf通維護了兩個不同的索引:一個用于讀取,一個用于寫入。
當你從 ByteBuf 讀取時,它的 readerIndex 将會被遞增已經被讀取的位元組數。同樣地,當你寫入 ByteBuf 時,它的writerIndex 也會被遞增
當調用readBytes時,readIndex會相應移動length位,如果readIndex移動後大于writeIndex則會抛異常。
當調用writeBytes時,writeIndex會相應移動length位,且通過ensureWritable方法實作自動擴容
其他常用API
getBytes | 擷取可讀位元組數組 |
setBytes | 寫入位元組 |
discardReadBytes | 廢棄已讀位元組 |
mark | 标記index |
reset | 将index重置到之前标記的位置(配合mark使用) |
isReadable | 如果至少有一個位元組可供讀取,則傳回 true |
isWritable | 如果至少有一個位元組可被寫入,則傳回 true |
readableBytes | 傳回可被讀取的位元組數 |
writableBytes | 傳回可被寫入的位元組數 |
capacity | 傳回 ByteBuf 可容納的位元組數。在此之後,它會嘗試再次擴充直到達到 maxCapacity() |
maxCapacity | 傳回 ByteBuf 可以容納的最大位元組數 |
hasArray | 如果 ByteBuf 由一個位元組數組支撐,則傳回 true |
array | 如果 ByteBuf 由一個位元組數組支撐則傳回該數組;否則,它将抛出一個UnsupportedOperationException 異常 |
ByteBuf緩沖分類
1、Heap buffer(堆緩沖區):
就是将資料存在JVM堆空間中,在沒有被池化的情況可以快速配置設定和釋放。
優點:由于資料是存儲在JVM堆中,是以可以快速的建立與快速的釋放,并且它提供了直接通路内部位元組數組的方法。
缺點:每次讀寫資料時,都需要先将資料複制到直接緩沖區中再進行網路傳輸。
2、Direct buffer(直接緩沖區):
直接緩沖區,在堆外直接配置設定記憶體空間,直接緩沖區并不會占用堆的容量空間,因為它是由作業系統在本地記憶體進行的資料配置設定。
優點:在使用Socket進行資料傳遞時,性能非常好,因為資料直接位于作業系統的本地記憶體中,是以不需要從JVM将資料複制到直接緩沖區中 。
缺點:因為Direct Buffer是直接在作業系統記憶體中的,是以記憶體空間的配置設定與釋放要比堆空間更加複雜,而且速度要慢一些。
注意:
如果你的資料包含在一個在堆上的配置設定的緩沖區中,那麼事實上,在通過套接字發送他之前,jvm将會在内部把你的緩沖區複制到一個直接緩沖區中;這樣配置設定釋放就比較浪費資源;
建議:
直接緩沖區并不支援通過位元組數組的方式來通路資料。對于後端業務的消息編解碼來說,推薦使用HeapByteBuf;對于I/O通信線程在讀寫緩沖區時,推薦使用DirectByteBuf;
3、Composite Buffer 複合緩沖區:
可以擁有以上兩種的緩沖區,通過一種聚合視圖來操作底層持有的多種類型Buffer。這種緩沖,jdk nio是沒有這種特性的。
ByteBuf主要實作類
pooled:池化,重用ByteBuf對象
Direct:直接記憶體,内部通過ByteBuffer實作,典型裝飾模式
Heap:堆記憶體,内部持有byte數組
(1)UnpooledDirectByteBuf:
在堆外進行記憶體配置設定的非記憶體池ByteBuf,内部持有ByteBuffer對象,相關操作委托給ByteBuffer實作。
(2)UnpooledHeapByteBuf:
基于堆記憶體配置設定非記憶體池ByteBuf,即内部持有byte數組。
(3)UnpooledUnsafeDirectByteBuf:
和另外一個類UnpooledDirectByteBuf差不多相同,差別在于UnpooledUnsafeDirectByteBuf内部使用基于PlatformDependent相關操作實作ByteBuf,依賴平台。
(4)ReadOnlyByteBufferBuf:
隻讀ByteBuf,内部持有ByteBuffer對象,相關操作委托給ByteBuffer實作,該ByteBuf限内部使用;
(5)FixedCompositeByteBuf:
用于将多個ByteBuf組合在一起,形成一個虛拟的隻讀ByteBuf對象,不允許寫入和動态擴充。内部使用Object[]将多個ByteBuf組合在一起,一旦FixedCompositeByteBuf對象建構完成,則不會被更改。
(6)CompositeByteBuf:
用于将多個ByteBuf組合在一起,形成一個虛拟的ByteBuf對象,支援讀寫和動态擴充。内部使用List組合多個ByteBuf。一般使用使用ByteBufAllocator的compositeBuffer()方法,Unpooled的工廠方法compositeBuffer()或wrappedBuffer(ByteBuf... buffers)建立CompositeByteBuf對象。
(7)PooledByteBuf:
基于記憶體池的ByteBuf,主要為了重用ByteBuf對象,提升記憶體的使用效率;适用于高負載,高并發的應用中。主要有PooledDirectByteBuf,PooledHeapByteBuf,PooledUnsafeDirectByteBuf三個子類,PooledDirectByteBuf是在堆外進行記憶體配置設定的記憶體池ByteBuf,PooledHeapByteBuf是基于堆記憶體配置設定記憶體池ByteBuf,PooledUnsafeDirectByteBuf也是在堆外進行記憶體配置設定的記憶體池ByteBuf,差別在于PooledUnsafeDirectByteBuf内部使用基于PlatformDependent相關操作實作ByteBuf,具有平台相關性。