UnpooledHeadByteBuf源码分析
1.簡單介紹
1.UnpooledHeadByteBuf簡介
UploadedHeadByteBuf是基于堆內存進行內存分配的字節緩存區,他沒有基于對象池的技術實現,意味著每次io的讀寫都會創建一個新的UnpooledHeadByteBuf,頻繁進行大塊內存的分配和回收對性能會造成一定的影響,但是相比于堆外內存的申請和釋放,他的成本低一點。
相比于PooledHeadbyteBuf,
UnpooledHeadByteBuf的實現原理更加簡單,也不容易出現內存管理方面的問題,因此在滿足性能的情況下,推薦使用UnpooledHeadByteBuf。
2.1成員變量
private final ByteBufAllocator alloc;private byte[] array;private ByteBuffer tmpNioBuf;ByteBufAllocate用于UnpooledHeapByteBuf的內存分配
byte數組作為緩存區
temNioBuf用于實現ByteBuf到ByteBuffer的轉換
2.2構造方法
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);}沒什么特殊的地方,很容易理解
3.動態擴展緩存。
在前面介紹AbstractByteBuf的時候,有一個setBytes()寫操作,我們還提到寫的方法與讀的方法的不一樣的地方在于它能夠動態擴展,setBytes()函數中,有一個ensureWritable(int minWritableBytes)函數專門用來檢查length:
1.如果長度參數小于零,拋出錯誤。
2.如果長度小于可讀長度(capacity() - writerIndex),老鐵沒毛病,過去吧。
3.如果長度大于最大可讀長度(maxCapacity - writerIndex),對不起,拋出錯誤。
4.當長度大于可讀長度小于最大可讀長度,這時候需要動態擴展了
計算最新的容量有ByteBufAllowcator幫我們完成,但是capacity(newCapacity)在AbstractByteBuf中并沒有實現,原因是動態擴展要根據ByteBuf是內存的還是堆的來決定。
說了這么多廢話,其實就是UnpooledHeadByteBuf這個類和他的兄弟UnpooledDirectByteBuf類都要實現Capacity這個方法,實現的方式不一樣而已。
來看他的代碼
如果新的容量小于零或者大于最大容量,拋出錯誤。
如果新的容量大于舊的容量,那么直接將新建一個緩存區,將舊的復制到新的中
如果新的容量小于舊的容量,就要進行縮小容量,就是新建一個新的緩存區,判斷readIndex和新的容量,如果readIndex大于新的容量,那么直接將readIndex和WriteIndex設置為新的緩存區的readIndex和WriteIndex;
如果readIndex小于新的容量,就要判斷writeIndex和新的容量,如果writeIndex大于新的容量,那么直接吧writeIndex設置為新的緩存區的writeIndex,然后進行緩存區的復制。
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());檢查函數就不必多說了,比較簡單。
首先檢查目標數組時候有低位數的內存地址,如果有,直接
然后檢查目標有沒有array緩存區,(實際上是檢查是不是Heap中的吧),如果是就
getBytes(index, dst.array(), dst.arrayOffset() + dstIndex, length);這個函數實際上就是System.arraycopy(array, index, dst, dstIndex, length)方法,實際上也驗證了我的判斷:和上面的動態擴展一樣,如果是同樣來自Heap中的ByteBuf的復制,用這個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.轉換成JDK ByteBuffer
public ByteBuffer nioBuffer(int index, int length) {ensureAccessible();return ByteBuffer.wrap(array, index, length).slice();}一個簡單的不能再簡單的函數:直接調用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();}} 超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的UnpooledHeadByteBuf源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AbstractReferenceCou
- 下一篇: UnpooledDirectByteBu