[編織訊息架構][netty源碼分析]11 UnpooledHeapByteBuf 與 ByteBufAllocator

來源:互聯網
上載者:User

標籤:啟動   length   test   緩衝   mat   img   ret   atom   控制   

 

每種ByteBuf都有相應的分配器ByteBufAllocator,類似原廠模式。我們先學習UnpooledHeapByteBuf與其對應的分配器UnpooledByteBufAllocator

如何知道alloc分配器那是個?

可以從官方下載的TimeServer 例子來學習,本項目已有源碼可在 TestChannelHandler.class裡斷點追蹤

從圖可以看出netty 4.1.8預設的ByteBufAllocator是PooledByteBufAllocator,可以參過啟動參數-Dio.netty.allocator.type unpooled/pooled 設定

細心的讀者可以看出分配ByteBuf只有pool跟unpool,但ByteBuf有很多類型,可能出於使用方面考慮,有時不一定設計太死板,太規範反而使學習成本很大

public final class ByteBufUtil {    static final ByteBufAllocator DEFAULT_ALLOCATOR;    static {        String allocType = SystemPropertyUtil.get(                "io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled");        allocType = allocType.toLowerCase(Locale.US).trim();        ByteBufAllocator alloc;        if ("unpooled".equals(allocType)) {            alloc = UnpooledByteBufAllocator.DEFAULT;        } else if ("pooled".equals(allocType)) {            alloc = PooledByteBufAllocator.DEFAULT;        } else {            alloc = PooledByteBufAllocator.DEFAULT;        }        DEFAULT_ALLOCATOR = alloc;    }}

 AbstractReferenceCountedByteBuf是統計引用總數處理,用到Atomic*技術。

refCnt是從1開始,每引用一次加1,釋放引用減1,當refCnt變成1時執行deallocate由子類實現

public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {    private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> refCntUpdater =            AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");    private volatile int refCnt = 1;     @Override    public ByteBuf retain() {        return retain0(1);    }    private ByteBuf retain0(int increment) {        for (;;) {            int refCnt = this.refCnt;            final int nextCnt = refCnt + increment;            if (nextCnt <= increment) {                throw new IllegalReferenceCountException(refCnt, increment);            }            if (refCntUpdater.compareAndSet(this, refCnt, nextCnt)) {                break;            }        }        return this;    }     @Override    public boolean release() {        return release0(1);    }    private boolean release0(int decrement) {        for (;;) {            int refCnt = this.refCnt;            if (refCnt < decrement) {                throw new IllegalReferenceCountException(refCnt, -decrement);            }            if (refCntUpdater.compareAndSet(this, refCnt, refCnt - decrement)) {                if (refCnt == decrement) {                    deallocate();                    return true;                }                return false;            }        }    }    protected abstract void deallocate();}

 

對於ByteBuf I/O 操作經常用的是 writeByte(byte[] bytes) readByte(byte[] bytes) 兩種
由於ByteBuf支援多種bytes對象,如 OutputStream、GatheringByteChannel、ByteBuffer、ByteBuf等,
我們只拿兩三種常用的API來做分析,其它邏輯大同小異
如果讀者有印象的話,通常底層只負責流程式控制制,實現交給應用程式層/子類處理,AbstractByteBuf.class writeByte/readByte 也是這種處理方式

public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {    //分配器    private final ByteBufAllocator alloc;    //資料    byte[] array;    //臨時ByteBuffer,用於內部緩衝    private ByteBuffer tmpNioBuf;        private UnpooledHeapByteBuf(            ByteBufAllocator alloc, byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) {        //省去部分代碼同邊界處理        super(maxCapacity);        this.alloc = alloc;        array = initialArray;        this.readerIndex = readerIndex;        this.writerIndex = writerIndex;    }    //擷取ByteBuffer容量    @Override    public int capacity() {        ensureAccessible();        return array.length;    }    @Override    public boolean hasArray() {        return true;    }    //擷取未經處理資料    @Override    public byte[] array() {        ensureAccessible();        return array;    }    //擴容/縮容    @Override    public ByteBuf capacity(int newCapacity) {        ensureAccessible();        //newCapacity參數邊界判斷        if (newCapacity < 0 || newCapacity > maxCapacity()) {            throw new IllegalArgumentException("newCapacity: " + newCapacity);        }        int oldCapacity = array.length;        //擴容處理,直接cp到新的array        if (newCapacity > oldCapacity) {            byte[] newArray = new byte[newCapacity];            System.arraycopy(array, 0, newArray, 0, array.length);            setArray(newArray);        } else if (newCapacity < oldCapacity) {            //減容處理            //這裡有兩種處理情況             //1.readerIndex > newCapacity 說明還有資料未處理直接將 readerIndex,writerIndex相等 newCapacity            //2.否則 writerIndex =Math.min(writerIndex,newCapacity),取最少值,然後直接複製資料                        //可以看出netty處理超出readerIndex、writerIndex 限界直接丟棄資料。。。。。。                        byte[] newArray = new byte[newCapacity];            int readerIndex = readerIndex();            if (readerIndex < newCapacity) {                int writerIndex = writerIndex();                if (writerIndex > newCapacity) {                    writerIndex = newCapacity                    this.writerIndex = writerIndex;                }                System.arraycopy(array, readerIndex, newArray, readerIndex, writerIndex - readerIndex);              //System.arraycopy(複製來源數組, 來源組起始座標, 目標數組, 目標數組起始座標, 複製資料長度);            } else {                this.readerIndex = newCapacity;                this.writerIndex = newCapacity;            }            setArray(newArray);        }        return this;    }}

 

未完侍。。。。。

[編織訊息架構][netty源碼分析]11 UnpooledHeapByteBuf 與 ByteBufAllocator

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.