日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

UnpooledHeadByteBuf源码分析

發(fā)布時(shí)間:2024/2/28 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UnpooledHeadByteBuf源码分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.簡(jiǎn)單介紹

1.UnpooledHeadByteBuf簡(jiǎn)介
UploadedHeadByteBuf是基于堆內(nèi)存進(jìn)行內(nèi)存分配的字節(jié)緩存區(qū),他沒(méi)有基于對(duì)象池的技術(shù)實(shí)現(xiàn),意味著每次io的讀寫(xiě)都會(huì)創(chuàng)建一個(gè)新的UnpooledHeadByteBuf,頻繁進(jìn)行大塊內(nèi)存的分配和回收對(duì)性能會(huì)造成一定的影響,但是相比于堆外內(nèi)存的申請(qǐng)和釋放,他的成本低一點(diǎn)。

相比于PooledHeadbyteBuf,
UnpooledHeadByteBuf的實(shí)現(xiàn)原理更加簡(jiǎn)單,也不容易出現(xiàn)內(nèi)存管理方面的問(wèn)題,因此在滿(mǎn)足性能的情況下,推薦使用UnpooledHeadByteBuf。

2.1成員變量

private final ByteBufAllocator alloc;private byte[] array;private ByteBuffer tmpNioBuf;

ByteBufAllocate用于UnpooledHeapByteBuf的內(nèi)存分配
byte數(shù)組作為緩存區(qū)
temNioBuf用于實(shí)現(xiàn)ByteBuf到ByteBuffer的轉(zhuǎn)換

2.2構(gòu)造方法

protected UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int maxCapacity) {this(alloc, initialArray, 0, initialArray.length, maxCapacity);}private UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) {super(maxCapacity);if (alloc == null) {throw new NullPointerException("alloc");}if (initialArray == null) {throw new NullPointerException("initialArray");}if (initialArray.length > maxCapacity) {throw new IllegalArgumentException(String.format("initialCapacity(%d) > maxCapacity(%d)", initialArray.length, maxCapacity));}this.alloc = alloc;setArray(initialArray);setIndex(readerIndex, writerIndex);}

沒(méi)什么特殊的地方,很容易理解

3.動(dòng)態(tài)擴(kuò)展緩存。

在前面介紹AbstractByteBuf的時(shí)候,有一個(gè)setBytes()寫(xiě)操作,我們還提到寫(xiě)的方法與讀的方法的不一樣的地方在于它能夠動(dòng)態(tài)擴(kuò)展,setBytes()函數(shù)中,有一個(gè)ensureWritable(int minWritableBytes)函數(shù)專(zhuān)門(mén)用來(lái)檢查length:
1.如果長(zhǎng)度參數(shù)小于零,拋出錯(cuò)誤。
2.如果長(zhǎng)度小于可讀長(zhǎng)度(capacity() - writerIndex),老鐵沒(méi)毛病,過(guò)去吧。
3.如果長(zhǎng)度大于最大可讀長(zhǎng)度(maxCapacity - writerIndex),對(duì)不起,拋出錯(cuò)誤。
4.當(dāng)長(zhǎng)度大于可讀長(zhǎng)度小于最大可讀長(zhǎng)度,這時(shí)候需要?jiǎng)討B(tài)擴(kuò)展了

int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);capacity(newCapacity);

計(jì)算最新的容量有ByteBufAllowcator幫我們完成,但是capacity(newCapacity)在AbstractByteBuf中并沒(méi)有實(shí)現(xiàn),原因是動(dòng)態(tài)擴(kuò)展要根據(jù)ByteBuf是內(nèi)存的還是堆的來(lái)決定。

說(shuō)了這么多廢話(huà),其實(shí)就是UnpooledHeadByteBuf這個(gè)類(lèi)和他的兄弟UnpooledDirectByteBuf類(lèi)都要實(shí)現(xiàn)Capacity這個(gè)方法,實(shí)現(xiàn)的方式不一樣而已。
來(lái)看他的代碼

如果新的容量小于零或者大于最大容量,拋出錯(cuò)誤。
如果新的容量大于舊的容量,那么直接將新建一個(gè)緩存區(qū),將舊的復(fù)制到新的中
如果新的容量小于舊的容量,就要進(jìn)行縮小容量,就是新建一個(gè)新的緩存區(qū),判斷readIndex和新的容量,如果readIndex大于新的容量,那么直接將readIndex和WriteIndex設(shè)置為新的緩存區(qū)的readIndex和WriteIndex;
如果readIndex小于新的容量,就要判斷writeIndex和新的容量,如果writeIndex大于新的容量,那么直接吧writeIndex設(shè)置為新的緩存區(qū)的writeIndex,然后進(jìn)行緩存區(qū)的復(fù)制。

System.arraycopy(array, readerIndex, newArray, readerIndex, writerIndex - readerIndex);

4.讀操作方法

@Overridepublic ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {checkDstIndex(index, length, dstIndex, dst.capacity());if (dst.hasMemoryAddress()) {PlatformDependent.copyMemory(array, index, dst.memoryAddress() + dstIndex, length);} else if (dst.hasArray()) {getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);} else {dst.setBytes(dstIndex, array, index, length);}return this;}@Overridepublic ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {checkDstIndex(index, length, dstIndex, dst.length);System.arraycopy(array, index, dst, dstIndex, length);return this;}

checkDstIndex(index, length, dstIndex, dst.capacity());檢查函數(shù)就不必多說(shuō)了,比較簡(jiǎn)單。
首先檢查目標(biāo)數(shù)組時(shí)候有低位數(shù)的內(nèi)存地址,如果有,直接

PlatformDependent.copyMemory(array, index, dst.memoryAddress() + dstIndex, length);

然后檢查目標(biāo)有沒(méi)有array緩存區(qū),(實(shí)際上是檢查是不是Heap中的吧),如果是就

getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);

這個(gè)函數(shù)實(shí)際上就是System.arraycopy(array, index, dst, dstIndex, length)方法,實(shí)際上也驗(yàn)證了我的判斷:和上面的動(dòng)態(tài)擴(kuò)展一樣,如果是同樣來(lái)自Heap中的ByteBuf的復(fù)制,用這個(gè)arraycopy方法就OK啦!

5.寫(xiě)操作

@Overridepublic ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {checkSrcIndex(index, length, srcIndex, src.capacity());if (src.hasMemoryAddress()) {PlatformDependent.copyMemory(src.memoryAddress() + srcIndex, array, index, length);} else if (src.hasArray()) {setBytes(index, src.array(), src.arrayOffset() + srcIndex, length);} else {src.getBytes(srcIndex, array, index, length);}return this;}@Overridepublic ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {checkSrcIndex(index, length, srcIndex, src.length);System.arraycopy(src, srcIndex, array, index, length);return this;}

嘿嘿,和讀操作一模一樣。‘

6.轉(zhuǎn)換成JDK ByteBuffer

public ByteBuffer nioBuffer(int index, int length) {ensureAccessible();return ByteBuffer.wrap(array, index, length).slice();}

一個(gè)簡(jiǎn)單的不能再簡(jiǎn)單的函數(shù):直接調(diào)用ByteBuffer的wrap方法搞定

public static ByteBuffer wrap(byte[] array,int offset, int length){try {return new HeapByteBuffer(array, offset, length);} catch (IllegalArgumentException x) {throw new IndexOutOfBoundsException();}} 超強(qiáng)干貨來(lái)襲 云風(fēng)專(zhuān)訪(fǎng):近40年碼齡,通宵達(dá)旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的UnpooledHeadByteBuf源码分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。