Netty分布式ByteBuf的分類方式源碼解析
上一小節(jié)簡單介紹了AbstractByteBuf這個(gè)抽象類, 這一小節(jié)對(duì)其子類的分類做一個(gè)簡單的介紹
ByteBuf根據(jù)不同的分類方式 會(huì)有不同的分類結(jié)果
我們首先看第一種分類方式
1.Pooled和Unpooled
pooled是從一塊內(nèi)存里去取一段連續(xù)內(nèi)存封裝成byteBuf
具體標(biāo)志是類名以Pooled開頭的ByteBuf, 通常就是Pooled類型的ByteBuf, 比如: PooledDirectByteBuf或者pooledHeapByteBuf
有關(guān)如何分配一塊連續(xù)的內(nèi)存, 我們之后的章節(jié)會(huì)講到
Unpooled是分配的時(shí)候直接調(diào)用系統(tǒng)api進(jìn)行實(shí)現(xiàn), 具體標(biāo)志是以Unpooled開頭的ByteBuf, 比如UnpooledDirectByteBuf, UnpooledHeapByteBuf
再看第二種分類方式
2.基于直接內(nèi)存的ByteBuf和基于堆內(nèi)存的ByteBuf
基于直接內(nèi)存的ByteBuf, 具體標(biāo)志是類名中包含單詞Direct的ByteBuf, 比如UnpooledDirectByteBuf, PooledDirectByteBuf等
基于堆內(nèi)存的ByteBuf, 具體標(biāo)志是類名中包含單詞heap的ByteBuf, 比如UnpooledHeapByteBuf, PooledHeapByteBuf
結(jié)合以上兩種方式, 這里通過其創(chuàng)建的方式去簡單對(duì)其分類做個(gè)解析
這里第一種分類的Pooled, 也就是分配一塊連續(xù)內(nèi)存創(chuàng)建byteBuf, 這一小節(jié)先不進(jìn)行舉例, 會(huì)在之后的小節(jié)講到
這里主要就看Unpooled, 也就是調(diào)用系統(tǒng)api的方式創(chuàng)建byteBuf, 在直接內(nèi)存和堆內(nèi)存中有什么區(qū)別
這里以UnpooledDirectByteBuf和UnpooledHeapByteBuf這兩種為例, 簡單介紹其創(chuàng)建方式:
首先看UnpooledHeapByteBuf的byetBuf, 這是基于內(nèi)存創(chuàng)建ByteBuf, 并且是直接調(diào)用系統(tǒng)api
我們看UnpooledHeapByteBuf的byetBuf的構(gòu)造方法:
protected UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) { this(alloc, new byte[initialCapacity], 0, 0, maxCapacity); }
這里調(diào)用了自身的構(gòu)造方法, 參數(shù)中創(chuàng)建了新的字節(jié)數(shù)組, 初始長度為初始化的內(nèi)存大小, 讀寫指針初始位置都是0, 并傳入了最大內(nèi)存大小
從這里看出, 有關(guān)堆內(nèi)存的Unpooled類型的分配, 是通過字節(jié)數(shù)組進(jìn)行實(shí)現(xiàn)的
再往下跟:
protected UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int maxCapacity) { this(alloc, initialArray, 0, initialArray.length, maxCapacity); }
繼續(xù)跟:
private UnpooledHeapByteBuf( ByteBufAllocator alloc, byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) { super(maxCapacity); //忽略驗(yàn)證代碼 this.alloc = alloc; setArray(initialArray); setIndex(readerIndex, writerIndex); }
跟到setAarry方法中:
private void setArray(byte[] initialArray) { array = initialArray; tmpNioBuf = null; }
將新創(chuàng)建的數(shù)組賦值為自身的array屬性
回到構(gòu)造函數(shù)中, 跟進(jìn)setIndex方法:
public ByteBuf setIndex(int readerIndex, int writerIndex) { //忽略驗(yàn)證代碼 setIndex0(readerIndex, writerIndex); return this; }
這里實(shí)際上是調(diào)用了AbstractByteBuf的setIndex方法
我們跟進(jìn)setIndex0方法中:
final void setIndex0(int readerIndex, int writerIndex) { this.readerIndex = readerIndex; this.writerIndex = writerIndex; }
這里設(shè)置了讀寫指針, 根據(jù)之前的調(diào)用鏈我們知道, 這里將讀寫指針位置都設(shè)置為了0
介紹完UnpooledHeapByteBuf的初始化, 我們繼續(xù)看UnpooledDirectByteBuf這個(gè)類的構(gòu)造, 顧明思議, 是基于堆外內(nèi)存, 并且同樣也是調(diào)用系統(tǒng)api的方式進(jìn)行實(shí)現(xiàn)的
我們看其構(gòu)造方法:
protected UnpooledDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) { super(maxCapacity); //忽略驗(yàn)證代碼 this.alloc = alloc; setByteBuffer(ByteBuffer.allocateDirect(initialCapacity)); }
我們關(guān)注下setByteBuffer中的參數(shù)ByteBuffer.allocateDirect(initialCapacity)
我們?cè)谶@里看到, 這里通過jdk的ByteBuffer直接調(diào)用靜態(tài)方法allocateDirect分配了一個(gè)基于直接內(nèi)存的ByteBuffer, 并設(shè)置了初始內(nèi)存
再跟到setByteBuffer方法中:
private void setByteBuffer(ByteBuffer buffer) { ByteBuffer oldBuffer = this.buffer; if (oldBuffer != null) { //代碼忽略 } this.buffer = buffer; tmpNioBuf = null; capacity = buffer.remaining(); }
我們看到在這里將分配的ByteBuf設(shè)置到當(dāng)前類的成員變量中
以上兩種實(shí)例, 我們會(huì)對(duì)上面所講到的兩種分類有個(gè)初步的了解
這里要注意一下, 基于堆內(nèi)存創(chuàng)建ByteBuf, 可以不用考慮對(duì)象回收, 因?yàn)樘摂M機(jī)會(huì)進(jìn)行垃圾回收, 但是堆外內(nèi)存在虛擬機(jī)的垃圾回收機(jī)制的作用域之外, 所以這里要考慮手動(dòng)回收對(duì)象
最后, 我們看第三種分類方式:
3.safe和unsafe
首先從名字上看, safe代表安全的, unsafe代表不安全的
這個(gè)安全與不安全的定義是什么呢
其實(shí)在我們jdk里面有unsafe對(duì)象, 可以通過unsafe對(duì)象直接拿到內(nèi)存地址, 基于內(nèi)存地址可以進(jìn)行讀寫操作
如果是Usafe類型的byteBuf, 則可以直接拿到byteBuf在jvm中的具體內(nèi)存, 可以通過調(diào)用jdk的Usafe對(duì)象進(jìn)行讀寫, 所以這里代表不安全
而非Usafe不能拿到j(luò)vm的具體內(nèi)存, 所以這里代表安全
具體標(biāo)志是如果類名中包含unsafe這個(gè)單詞的ByteBuf, 可以認(rèn)為是一個(gè)unsafe類型的ByteBuf, 比如PooledUnsafeHeapByteBuf或者PooledUnsafeDirectByteBuf
以PooledUnsafeHeapByteBuf的_getByte方法為例:
protected byte _getByte(int index) { return UnsafeByteBufUtil.getByte(memory, idx(index)); }
這里memory代表byebuffer底層分配內(nèi)存的首地址, idx(index)代表當(dāng)前指針index距內(nèi)存memory的偏移地址, UnsafeByteBufUtil的getByte方法, 就可以直接通過這兩個(gè)信息通過jdk底層的unsafe對(duì)象拿到j(luò)dk底層的值
有關(guān)AbstractByteBuf的主要實(shí)現(xiàn)類和繼承關(guān)系, 如下圖所示:
以上就是Netty分布式ByteBuf的分類方式源碼解析的詳細(xì)內(nèi)容,更多關(guān)于Netty分布式ByteBuf分類方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實(shí)現(xiàn)電影院訂票系統(tǒng)代碼
這篇文章主要介紹了Java實(shí)現(xiàn)電影院訂票系統(tǒng)代碼,代碼實(shí)現(xiàn)了界面類登錄注冊(cè)類,用戶類等,具有一定參考價(jià)值,需要的朋友可以參考下。2017-11-11java 實(shí)現(xiàn)圖片像素質(zhì)量壓縮與圖片長寬縮放
這篇文章主要介紹了java 實(shí)現(xiàn)圖片像素質(zhì)量壓縮與圖片長寬縮放,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11java基于dom4j包實(shí)現(xiàn)對(duì)XML解析的方法
這篇文章主要介紹了java基于dom4j包實(shí)現(xiàn)對(duì)XML解析的方法,結(jié)合實(shí)例形式分析了java針對(duì)xml格式數(shù)據(jù)的相關(guān)解析操作實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-05-05JAVA 筆記 ClassLoader.getResourceAsStream() 與 Class.getResourc
這篇文章主要介紹了JAVA 筆記 ClassLoader.getResourceAsStream() 與 Class.getResourceAsStream()的區(qū)別,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07