ByteBuf類繼承關係圖以下:java
ReferenceCounted:對象引用計數器,初始化ReferenceCounted對象時,引用數量refCnt爲1,調用retain()可增長refCnt,release()用於減小refCnt。refCnt爲1時,說明對象實際不可達,release()方法將當即調用deallocate()釋放對象。若是refCnt爲0,說明對象被錯誤的引用。在AbstractReferenceCountedByteBuf源碼分析小節將詳細介紹ReferenceCounted的原理。後端
ByteBuf:實現接口ReferenceCounted和Comparable,實現ReferenceCounted使得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用於字節序不一樣時轉換字節序。高併發
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:提供修改對象引用計數器相關操做的默認實現。
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主要分爲兩類:
經驗代表,在I/O通訊線程的讀寫緩衝區使用DirectByteBuf,後端業務消息的編解碼模塊使用HeapByteBuf,這樣組合能夠達到性能最優。
從內存回收角度看,ByteBuf也分爲兩類:
本節重點介紹ByteBuf繼承家族的各個成員,詳細功能後續將經過源碼講解,下一節介紹AbstractByteBuf源碼。
歡迎指出本文有誤的地方,轉載請註明原文出處https://my.oschina.net/7001/blog/743240