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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AbstractByteBuf源码分析

發布時間:2024/2/28 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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);方法,點進去看一看
發現他是父類的抽象方法

public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int 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);檢查是否可讀,這個方法的厲害之處在于它可以動態擴展緩存區。
上代碼!

@Overridepublic ByteBuf ensureWritable(int minWritableBytes) {if (minWritableBytes < 0) {throw new IllegalArgumentException(String.format("minWritableBytes: %d (expected: >= 0)", minWritableBytes));}if (minWritableBytes <= writableBytes()) {return this;}if (minWritableBytes > maxCapacity - writerIndex) {throw new IndexOutOfBoundsException(String.format("writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",writerIndex, minWritableBytes, maxCapacity, this));int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);// Adjust to the new capacity.capacity(newCapacity);return this;}

1.如果長度參數小于零,拋出錯誤。
2.如果長度小于可讀長度(capacity() - writerIndex),老鐵沒毛病,過去吧。
3.如果長度大于最大可讀長度(maxCapacity - writerIndex),對不起,拋出錯誤。
4.最重要的情況大于可讀長度小于最大可讀長度

capacity() - writerIndex< n <maxCapacity - writerIndex

這時候需要動態擴展長度了,看回這段代碼

int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);// Adjust to the new capacity.capacity(newCapacity);return this;

我們在他的父類ByteBuf中看到alloc()返回這個ByteBuf的分配者對象,所以先用分配者對象調用calculateNewCapacity計算出一個適合的新的容量capacity。
然后調用 capacity(newCapacity)設置新的容量,點進去看一看!發現還是父類的方法

public abstract ByteBuf capacity(int newCapacity);

和上面的getBytes()方法一樣沒有實現,是不是和這個方法一樣和ByteBuf是內存中的還是堆中的有關系呢?
沒錯,就是這樣,capacity(newCapacity)進行擴容處理,當然會因為它的位置而采取不同的處理啊!

代碼讀到這里,感覺十分行云流水,沒有什么地方特別難懂,下一個就是AbstractReferenceCountedByteBuf類了,從名字一看就知道是和計數器有關,肯定不難!

總結

以上是生活随笔為你收集整理的AbstractByteBuf源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。