導(dǎo)讀
原創(chuàng)文章在跳,轉(zhuǎn)載請注明出處。
本文源碼地址:netty-source-code-analysis
本文所使用的netty版本4.1.6.Final:帶注釋的netty源碼
本文簡要地介紹ByteBuf
的結(jié)構(gòu)鸣驱、主要api和創(chuàng)建方法哮内。
1 ByteBuf的結(jié)構(gòu)
每一個ByteBuf
都有一個可容納的字節(jié)上限叫capacity
圈暗。在ByteBuf
中通過兩個指針readerIndex
和writerIndex
將整個個ByteBuf
劃分成3個部分,分別是已丟棄部分
缘挽、可讀部分
和可寫部分
瞄崇,示意圖如下。
+-------------------+------------------+------------------+
| 已丟棄 | 可讀 | 可寫 |
| | (CONTENT) | |
+-------------------+------------------+------------------+
| | | |
0 <= readerIndex <= writerIndex <= capacity
readerIndex
壕曼、writerIndex
和capacity
之間滿足簡單地數(shù)學(xué)關(guān)系0 <= readerIndex <= writerIndex <= capcity
苏研。
一個新建的從未進(jìn)行過讀寫操作的ByteBuf
,readerIndex
和writerIndex
都為0腮郊。整個空間都是可寫部分摹蘑。
+---------------------------------------------------------+
| 可寫 |
| |
+---------------------------------------------------------+
| |
0 capacity
readerIndex
writerIndex
現(xiàn)在往其中寫入一些數(shù)據(jù),寫數(shù)據(jù)的過程會引起writerIndex
的移動轧飞,writerIndex
移動的最大值為capacity
衅鹿,寫數(shù)據(jù)的過程中readerIndex
保持不變。
+--------------------------------------+------------------+
| 可讀 | 可寫 |
| (CONTENT) | |
+--------------------------------------+------------------+
| | |
0 <= writerIndex <= capacity
readerIndex
接著讀取一些數(shù)據(jù)过咬,讀數(shù)據(jù)的過程會引起readerIndex
的移動大渤,readerIndex
的最大值為writerIndex
,在讀數(shù)據(jù)的過程中writerIndex
保持不變掸绞。已經(jīng)被讀取過的部分就成了已丟棄部分泵三。
+-------------------+------------------+------------------+
| 已丟棄 | 可讀 | 可寫 |
| | (CONTENT) | |
+-------------------+------------------+------------------+
| | | |
0 <= readerIndex <= writerIndex <= capacity
2 ByteBuf的主要方法
2.1 write族方法
write
族方法用來向ByteBuf
中寫入各種類型的數(shù)據(jù),比如writeBytes
、writeChar
烫幕、writeInt
等俺抽。另外支持寫入小端字節(jié)序數(shù)據(jù),比如writeIntLE
较曼、writeLongLE
等凌埂。
write
族方法的調(diào)用時寫入數(shù)據(jù)的起始位置就是當(dāng)前writerIndex
指向的位置,寫入數(shù)據(jù)會引起writerIndex
的移動诗芜。
2.2 read族方法
read
族方法用來從ByteBuf
中讀取數(shù)據(jù),比如readBytes
埃疫、writeBytes
伏恐、writeLong
等。同樣也支持讀取小端字節(jié)序數(shù)據(jù)栓霜,比如readIntLE
翠桦、readLongLE
等。
read
族方法的調(diào)用會引起readerIndex
的移動胳蛮。
2.3 set
族方法
和write
族方法一樣销凑,set
族方法同樣用來向ByteBuf
中寫入各種類型的數(shù)據(jù)。write
能寫入的數(shù)據(jù)set
也能仅炊,比如writeInt
和setInt
斗幼。不同的是set
族方法在調(diào)用時需要傳遞一個索引參數(shù),也就是說需要指定寫入數(shù)據(jù)的位置抚垄,比如writeInt(int value)
和setInt(int index, int value)
蜕窿。
set
族方法的調(diào)用不會引起writerIndex
的移動。
2.4 get
族方法
和read
族方法一樣呆馁,get
族方法同樣用來從ByteBuf
中讀取數(shù)據(jù)桐经。比如有getInt
、getLong
方法浙滤。與read
族方法不一樣的是在調(diào)用時需要傳遞一個索引參數(shù)阴挣,也就是說需要指定讀取數(shù)據(jù)的位置,比如getInt(int index)
和readInt()
纺腊。
read
族方法的調(diào)用不會引起readerIndex
的移動畔咧。
2.5 讀取/設(shè)置 Index的方法
ByteBuf
提供了writerIndex()
和readerIndex()
方法分別可以返回當(dāng)前的writerIndex
和readerIndex
。
除了read
和write
方法可以改變readerIndex
和writerIndex
摹菠,ByteBuf
也提供了可以手動設(shè)置readerIndex
的readerIndex(int readerIndex)
及手動設(shè)置writerIndex
的writerIndex(int writerIndex)
方法盒卸。
2.6 slice方法
slice
方法將當(dāng)前ByteBuf
的可讀數(shù)據(jù)區(qū)映射到一個新的ByteBuf
,并返回這個新的ByteBuf
次氨。這個新的ByteBuf
與原ByteBuf
共享數(shù)據(jù)區(qū)域蔽介,但是擁有獨(dú)立的readerIndex
和writerIndex
。
也提供了slice(int index, int length)
方法可以指定映射的數(shù)據(jù)區(qū)域范圍。
對新的ByteBuf
數(shù)據(jù)的修改同樣會影響到的原來的ByteBuf
的數(shù)據(jù)虹蓄,反之亦然犀呼。
2.7 duplicate方法
duplicate
方法將當(dāng)前ByteBuf
的整個數(shù)據(jù)區(qū)映射到一個新的ByteBuf
,并返回這個新的ByteBuf
薇组。這個新的ByteBuf
與原ByteBuf
共享數(shù)據(jù)區(qū)域外臂,但是擁有獨(dú)立的readerIndex
和writerIndex
。
對新的ByteBuf
數(shù)據(jù)的修改同樣會影響到的原來的ByteBuf
的數(shù)據(jù)律胀,反之亦然宋光。
2.8 copy方法
copy
方法返回當(dāng)前ByteBuf
的一個復(fù)制品,新的ByteBuf
擁有與原來的ByteBuf
不一樣的數(shù)據(jù)區(qū)域炭菌,readerIndex
和writerIndex
也是獨(dú)立的罪佳。
同樣提供了copy(int index, int length)
方法可以指定復(fù)制的數(shù)據(jù)區(qū)域范圍。
對新的ByteBuf
數(shù)據(jù)的修改不會影響到原來的ByteBuf
黑低,反之亦然赘艳。
2.9 retain和release方法
ByteBuf
使用引用計數(shù)法來表示當(dāng)前ByteBuf
被引用的次數(shù),如果一個ByteBuf
的被引用次數(shù)為0克握,則釋放該ByteBuf
對應(yīng)的內(nèi)存蕾管。
3 ByteBuf的主要實現(xiàn)及創(chuàng)建
ByteBuf的主要實現(xiàn)類圖如下圖所示,總體上分為Pooled
和UnPooled
兩類菩暗,顧名思義為池化的和非池化的掰曾,又根據(jù)分配的是直接內(nèi)存還是堆內(nèi)存分為HeapByteBuf
和DirectByteBuf
。
3.1 通過ByteBufAllocator創(chuàng)建
ByteBufAllocator
有兩個實現(xiàn)分別為PooledByteBufAllocator
和UnpooledByteBufAllocator
對應(yīng)分配出來是的PooledByteBuf
和UnpooledByteBuf
停团。
PooledByteBufAllocator
將在后續(xù)的文章中重點(diǎn)分析婴梧,而UnpooledByteBufAllocator
則比較簡單,不再贅述客蹋。
3.2 通過包裹ByteBuffer及byte[]創(chuàng)建
使用Unpooled.wrappedBuffer
方法可以對jdkButeBuffer
及byte[]
進(jìn)行包裹創(chuàng)建出一個UnpooledByteBuf
塞蹭。
4 總結(jié)
ByteBuf
主要api有read/write,get/set讶坯,slice番电,duplicate,copy等系列方法辆琅。實現(xiàn)類上主要分為Unpooled
和Pooled
漱办,并且支持分配HeapByteBuf
及DirectByteBuf
。
關(guān)于作者
王建新婉烟,轉(zhuǎn)轉(zhuǎn)架構(gòu)部服務(wù)治理負(fù)責(zé)人娩井,主要負(fù)責(zé)服務(wù)治理、RPC框架似袁、分布式調(diào)用跟蹤洞辣、監(jiān)控系統(tǒng)等咐刨。愛技術(shù)、愛學(xué)習(xí)扬霜,歡迎聯(lián)系交流定鸟。