AbstractByteBuf源码分析
1.成員變量
static final ResourceLeakDetector<ByteBuf> leakDetector = new ResourceLeakDetector<ByteBuf>(ByteBuf.class);int readerIndex;int writerIndex;private int markedReaderIndex;private int markedWriterIndex;private int maxCapacity;private SwappedByteBuf swappedBuf;readerIndex,writeIndex,markedReaderIndex,markWriterIndex,maxCapacity這些都是很平常的變量。
而它的這兩個屬性,應該引起我們的注意:
一個是SwappedByteBuf swappedBuf;
這個是大端序列與小端序列的轉換。
二個是ResourceLeakDetector
這個是Netty用來解決內存泄漏檢測機制,非常重要。
由于AbstractByteBuf它繼承了抽象類ByteBuf,所以它”不得不”把它的所有瑣瑣碎碎的函數給實現了,大部分都是一些返回信息的函數,這里就不再贅述,直接上難點!
2.讀操作簇
取其中之一進行分析吧
@Overridepublic ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {checkReadableBytes(length);getBytes(readerIndex, dst, dstIndex, length);readerIndex += length;return this;}每個讀操作都會先調用checkReadableBytes(length);檢查是否可讀
protected final void checkReadableBytes(int minimumReadableBytes) {ensureAccessible();if (minimumReadableBytes < 0) {throw new IllegalArgumentException("minimumReadableBytes: " + minimumReadableBytes + " (expected: >= 0)");}if (readerIndex > writerIndex - minimumReadableBytes) {throw new IndexOutOfBoundsException(String.format("readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s",readerIndex, minimumReadableBytes, writerIndex, this));}} protected final void ensureAccessible() {if (refCnt() == 0) {throw new IllegalReferenceCountException(0);}}這個函數非常簡單,先檢查計數器refcnt是否等于0,等于零說明被錯誤地引用,然后檢查傳進去的長度參數,小于零拋出錯誤,加上readIndex大于writeIndex也會拋出錯誤。
之后會調用getBytes(readerIndex, dst, dstIndex, length);方法,點進去看一看
發現他是父類的抽象方法
為什么沒有實現這個方法呢,原因很簡單,getBytes方法根據調用函數的對象的不同會采取不同策略,這個函數調用對象可以是一個內存中的ByteBuf也可以是一個堆中的ByteBuf,所以它就沒實現羅。
3.寫操作簇
有人問,讀和寫不是差不多嘛,其實不然,寫操作有個不同之處,他可以動態擴展內存,是非常值得我們學習的地方。在隨便找一個寫操作的函數進行一番分析
@Overridepublic ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {ensureAccessible();ensureWritable(length);setBytes(writerIndex, src, srcIndex, length);writerIndex += length;return this;}ensureAccessible()檢查計數器是否為零, ensureWritable(length);檢查是否可讀,這個方法的厲害之處在于它可以動態擴展緩存區。
上代碼!
1.如果長度參數小于零,拋出錯誤。
2.如果長度小于可讀長度(capacity() - writerIndex),老鐵沒毛病,過去吧。
3.如果長度大于最大可讀長度(maxCapacity - writerIndex),對不起,拋出錯誤。
4.最重要的情況大于可讀長度小于最大可讀長度
這時候需要動態擴展長度了,看回這段代碼
int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);// Adjust to the new capacity.capacity(newCapacity);return this;我們在他的父類ByteBuf中看到alloc()返回這個ByteBuf的分配者對象,所以先用分配者對象調用calculateNewCapacity計算出一個適合的新的容量capacity。
然后調用 capacity(newCapacity)設置新的容量,點進去看一看!發現還是父類的方法
和上面的getBytes()方法一樣沒有實現,是不是和這個方法一樣和ByteBuf是內存中的還是堆中的有關系呢?
沒錯,就是這樣,capacity(newCapacity)進行擴容處理,當然會因為它的位置而采取不同的處理啊!
代碼讀到這里,感覺十分行云流水,沒有什么地方特別難懂,下一個就是AbstractReferenceCountedByteBuf類了,從名字一看就知道是和計數器有關,肯定不難!
總結
以上是生活随笔為你收集整理的AbstractByteBuf源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ByteBuf的源码分析
- 下一篇: AbstractReferenceCou