UnpooledHeadByteBuf源码分析
1.簡(jiǎn)單介紹
1.UnpooledHeadByteBuf簡(jiǎn)介
UploadedHeadByteBuf是基于堆內(nèi)存進(jìn)行內(nèi)存分配的字節(jié)緩存區(qū),他沒(méi)有基于對(duì)象池的技術(shù)實(shí)現(xiàn),意味著每次io的讀寫都會(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)題,因此在滿足性能的情況下,推薦使用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()寫操作,我們還提到寫的方法與讀的方法的不一樣的地方在于它能夠動(dòng)態(tài)擴(kuò)展,setBytes()函數(shù)中,有一個(gè)ensureWritable(int minWritableBytes)函數(shù)專門用來(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ò)展了
計(jì)算最新的容量有ByteBufAllowcator幫我們完成,但是capacity(newCapacity)在AbstractByteBuf中并沒(méi)有實(shí)現(xiàn),原因是動(dòng)態(tài)擴(kuò)展要根據(jù)ByteBuf是內(nèi)存的還是堆的來(lái)決定。
說(shuō)了這么多廢話,其實(shí)就是UnpooledHeadByteBuf這個(gè)類和他的兄弟UnpooledDirectByteBuf類都要實(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ù)制。
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)存地址,如果有,直接
然后檢查目標(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.寫操作
@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)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的UnpooledHeadByteBuf源码分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: AbstractReferenceCou
- 下一篇: UnpooledDirectByteBu