深刻研究Netty框架之ByteBuf家族

ByteBuf類繼承關係圖以下:java

ReferenceCounted:對象引用計數器,初始化ReferenceCounted對象時,引用數量refCnt爲1,調用retain()可增長refCnt,release()用於減小refCnt。refCnt爲1時,說明對象實際不可達,release()方法將當即調用deallocate()釋放對象。若是refCnt爲0,說明對象被錯誤的引用。在AbstractReferenceCountedByteBuf源碼分析小節將詳細介紹ReferenceCounted的原理。後端

ByteBuf:實現接口ReferenceCounted和Comparable,實現ReferenceCounted使得ByteBuf具有引用計數的能力,方便跟蹤ByteBuf對象分配和釋放。數組

  • ByteBuf直接子類

EmptyByteBuf:用於構建空ByteBuf對象,capacity和maxCapacity均爲0。網絡

ReplayingDecoderBuffer:用於構建在IO阻塞條件下實現無阻塞解碼的特殊ByteBuf對象,當要讀取的數據還未接收徹底時,拋出異常,交由ReplayingDecoder處理。併發

SwappedByteBuf:用於構建具備切換字節順序功能的ByteBuf對象,默認ByteBuf對象使用BIG_ENDIAN(大字節序)存儲數據,SwappedByteBuf能夠在BIG_ENDIAN和LITTLE_ENDIAN之間自由切換。TCP/IP各層協議均採用網絡字節序(BIG_ENDIAN),關於字節序的更多內容不詳細介紹。app

WrappedByteBuf:用於裝飾ByteBuf對象,主要有AdvancedLeakAwareByteBuf、SimpleLeakAwareByteBuf和UnreleasableByteBuf三個子類。這裏WrappedByteBuf使用裝飾者模式裝飾ByteBuf對象,AdvancedLeakAwareByteBuf用於對全部操做記錄堆棧信息,方便監控內存泄漏;SimpleLeakAwareByteBuf只記錄order(ByteOrder endianness)的堆棧信息;UnreleasableByteBuf用於阻止修改對象引用計數器refCnt的值。ide

AbstractByteBuf:提供ByteBuf的默認實現,同時組合ResourceLeakDetector和SwappedByteBuf的能力,ResourceLeakDetector是內存泄漏檢測工具,SwappedByteBuf用於字節序不一樣時轉換字節序。高併發

  • AbstractByteBuf直接子類

AbstractDerivedByteBuf:提供派生ByteBuf的默認實現,主要有DuplicatedByteBuf、ReadOnlyByteBuf和SlicedByteBuf。工具

DuplicatedByteBuf使用裝飾者模式建立ByteBuf的複製對象,使得複製後的對象與原對象共享緩衝區的內容,可是獨立維護本身的readerIndex和writerIndex。部分源碼以下:源碼分析

private final ByteBuf buffer;

    public DuplicatedByteBuf(ByteBuf buffer) {
        super(buffer.maxCapacity());
        //共享緩衝區內容
        if (buffer instanceof DuplicatedByteBuf) {
            this.buffer = ((DuplicatedByteBuf) buffer).buffer;
        } else {
            this.buffer = buffer;
        }
        //調用自身的setIndex方法維護readerIndex和writerIndex
        setIndex(buffer.readerIndex(), buffer.writerIndex());
    }
    //全部操做都是經過調用被裝飾對象buffer的相應方法實現
    @Override
    public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
        buffer.getBytes(index, dst, dstIndex, length);
        return this;
    }
    @Override
    public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
        buffer.getBytes(index, dst, dstIndex, length);
        return this;
    }

ReadOnlyByteBuf使用裝飾者模式建立ByteBuf的只讀對象,該只讀對象與原對象共享緩衝區的內容,可是獨立維護本身的readerIndex和writerIndex,以後全部的寫操做都被限制;部分源碼以下:

private final ByteBuf buffer;

    public ReadOnlyByteBuf(ByteBuf buffer) {
        super(buffer.maxCapacity());

        if (buffer instanceof ReadOnlyByteBuf || buffer instanceof DuplicatedByteBuf) {
            this.buffer = buffer.unwrap();
        } else {
            this.buffer = buffer;
        }
        setIndex(buffer.readerIndex(), buffer.writerIndex());
    }
    @Override
    protected void _setLong(int index, long value) {
        throw new ReadOnlyBufferException();
    }

    @Override
    public int setBytes(int index, InputStream in, int length) {
        throw new ReadOnlyBufferException();
    }

SlicedByteBuf使用裝飾者模式建立ByteBuf的一個子區域ByteBuf對象,返回的ByteBuf對象與當前ByteBuf對象共享緩衝區的內容,可是維護本身獨立的readerIndex和writerIndex,容許寫操做。

AbstractReferenceCountedByteBuf:提供修改對象引用計數器相關操做的默認實現。

  • AbstractReferenceCountedByteBuf直接子類

CompositeByteBuf:用於將多個ByteBuf組合在一塊兒,造成一個虛擬的ByteBuf對象,支持讀寫和動態擴展。內部使用List<Component>組合多個ByteBuf。推薦使用ByteBufAllocator的compositeBuffer()方法,Unpooled的工廠方法compositeBuffer()或wrappedBuffer(ByteBuf... buffers)建立CompositeByteBuf對象。

FixedCompositeByteBuf:用於將多個ByteBuf組合在一塊兒,造成一個虛擬的只讀ByteBuf對象,不容許寫入和動態擴展。內部使用Object[]將多個ByteBuf組合在一塊兒,一旦FixedCompositeByteBuf對象構建完成,則不會被更改。

PooledByteBuf<T>:基於內存池的ByteBuf,主要爲了重用ByteBuf對象,提高內存的使用效率;適用於高負載,高併發的應用中。主要有PooledDirectByteBuf,PooledHeapByteBuf,PooledUnsafeDirectByteBuf三個子類,PooledDirectByteBuf是在堆外進行內存分配的內存池ByteBuf,PooledHeapByteBuf是基於堆內存分配內存池ByteBuf,PooledUnsafeDirectByteBuf也是在堆外進行內存分配的內存池ByteBuf,區別在於PooledUnsafeDirectByteBuf內部使用基於PlatformDependent相關操做實現ByteBuf,具備平臺相關性。

ReadOnlyByteBufferBuf:只讀ByteBuf,內部持有ByteBuffer對象,相關操做委託給ByteBuffer實現,該ByteBuf限內部使用,ReadOnlyByteBufferBuf還有一個子類ReadOnlyUnsafeDirectByteBuf。

UnpooledDirectByteBuf:在堆外進行內存分配的非內存池ByteBuf,內部持有ByteBuffer對象,相關操做委託給ByteBuffer實現。

UnpooledHeapByteBuf:基於堆內存分配非內存池ByteBuf,即內部持有byte數組。

UnpooledUnsafeDirectByteBuf:與UnpooledDirectByteBuf相同,區別在於UnpooledUnsafeDirectByteBuf內部使用基於PlatformDependent相關操做實現ByteBuf,具備平臺相關性。

到此,ByteBuf繼承家族的各個成員對應的相關功能已介紹完成。

總結:

從內存分配角度看,ByteBuf主要分爲兩類:

  • 堆內存(HeapByteBuf)字節緩衝區:特色是內存的分配和回收速度快,能夠被JVM自動回收;缺點是進行Socket的I/O讀寫須要額外進行一次內存複製,即將內存對應的緩衝區複製到內核Channel中,性能會有必定程度降低。
  • 直接內存(DirectByteBuf)字節緩衝區:在堆外進行內存分配,相比堆內存,分配和回收速度稍慢。但用於Socket的I/O讀寫時,少一次內存複製,速度比堆內存字節緩衝區快。

經驗代表,在I/O通訊線程的讀寫緩衝區使用DirectByteBuf,後端業務消息的編解碼模塊使用HeapByteBuf,這樣組合能夠達到性能最優。

從內存回收角度看,ByteBuf也分爲兩類:

  • 基於內存池的ByteBuf:優勢是能夠重用ByteBuf對象,經過本身維護一個內存池,能夠循環利用建立的ByteBuf,提高內存的使用效率,下降因爲高負載致使的頻繁GC。適用於高負載,高併發的應用中。推薦使用基於內存池的ByteBuf。
  • 非內存池的ByteBuf:優勢是管理和維護相對簡單。

本節重點介紹ByteBuf繼承家族的各個成員,詳細功能後續將經過源碼講解,下一節介紹AbstractByteBuf源碼。

歡迎指出本文有誤的地方,轉載請註明原文出處https://my.oschina.net/7001/blog/743240

相關文章
相關標籤/搜索