問題:
- ByteBuffと伝統的なByteBuffの差ネッティーは何ですか?
- HeapByteBufとDirectByteBuf違いは?HeapByteBuf:原因をコピーする必要があるため、ヒープ・メモリ、短所、ソケットの送信時間を利用して、ゆっくりとDirectByteBuf:外部メモリヒープは、ゼロコピーを使用することができます
アウトライン
netty ByteBuf 存在两个指针,分成三个区域: 已读区(可丢弃),未读区(未读),可写区 。不像之前JDK 的 ByteBuffer 中只有一个position 指针。例如以下示例 :
パブリック静的無効メイン(文字列[] args){ ByteBufferのバッファ= ByteBuffer.allocate(88)。 文字列値=「ネッティー~~」。 buffer.put(value.getBytes())。 //このフリップ()メソッドは、呼び出されていない場合、誤った場所を読まれることに注意してください buffer.flip(); バイト[] VARRAY =新しいバイト[buffer.remaining()]。 BUFFER.GET(VARRAY)。 文字列結果=新しい文字列(VARRAY)。 System.out.println(結果)。 }
概述一下netty ByteBuff 的特点 :
- APIが豊富で、かつ存在readIndex writeIndex二つのポインタ、読み、書きやすいです
- 動的な拡張
- この方法は、互換性のあるJDKのByteBufferを提供します
分類
内存池,循环利用创建的 ByteBuf 对象提升内存使用效率,降低由于高负载导致的频繁 GC .
PooledByteBuf 抽象类的子类 :
- PooledDirectByteBuf
- PooledHeapByteBuf
- クラス図の構造を見てPooledUnsafeDirectByteBuf
ソースコード解析
ソースコード解析AbstractByteBuf
@オーバーライド 公共ByteBufのreadBytes(ByteBuf DST、INT dstIndex、int型の長さ){ checkReadableBytes(長さ)。 サブクラス実装と呼ば//抽象メソッド GetBytesメソッド(readerIndex、DST、dstIndex、長さ); readerIndex + =長さ。 これを返します。 }
看一下写操作
@オーバーライド 公共ByteBufのwriteBytes(バイト[] SRC、INT srcIndex、INT長){ ensureWritable(長さ)。 setBytes(writerIndex、SRC、srcIndex、長さ); writerIndex + =長さ。 これを返します。 } @オーバーライド 公共ByteBuf ensureWritable(INT minWritableBytes){ IF(minWritableBytes <0){ ((String.Formatの新しいIllegalArgumentExceptionをスローし "minWritableBytes:%のD(予想:> = 0)"、minWritableBytes))。 } IF(minWritableBytes <= writableBytes()){ これを返します。 } IF(minWritableBytes> MAXCAPACITY - writerIndex){ ((String.Formatのを新しいはIndexOutOfBoundsExceptionを投げます 、: "%sのwriterIndex(%d)は+ minWritableBytes(%d)はMAXCAPACITY率(%D)を超えます" writerIndex、minWritableBytes、MAXCAPACITY、この)); } // 2の電源に電流容量を正規化。 INT newCapacity = calculateNewCapacity(writerIndex + minWritableBytes)。 //新しい容量を調整します。 容量(newCapacity)。 これを返します。 } / ** *新しい容量ではなく、すべてのこのような単純な考え方の突然倍増のが、少しの増加を計算します。 * * / プライベートint型calculateNewCapacity(int型minNewCapacity){ 最終int型MAXCAPACITY = this.maxCapacity。 最終INT閾値= 1048576 * 4。// 4のMIBページ IF(minNewCapacity ==閾値){ しきい値を返します。 } //しきい値を超える場合は、倍増ちょうどしきい値によって増加しません。 IF(minNewCapacity>閾値){ int型newCapacity = minNewCapacity /しきい値*しきい値。 IF(newCapacity> MAXCAPACITY - 閾値){ newCapacity = MAXCAPACITY。 }他{ newCapacity + =閾値。 } newCapacityを返します。 } //未しきい値を超えます。64から始まる、4 MIBへのダブルアップ。 int型newCapacity = 64; 一方、(newCapacity <minNewCapacity){ newCapacity << = 1。 } Math.min(newCapacity、MAXCAPACITY)を返します。 }
丢弃已读区域,复用缓冲区
@オーバーライド discardReadBytes ByteBufパブリック(){ ensureAccessible(); IF(readerIndex == 0){ これを返します。 } もし(readerIndex!= writerIndex){ //サブクラス実装、コピーするバイト配列、前方の書き込み領域 setBytes(0、この、readerIndex、writerIndex - readerIndex)。 writerIndex - = readerIndex。 adjustMarkers(readerIndex)。 readerIndex = 0; }他{ adjustMarkers(readerIndex)。 writerIndex = readerIndex = 0。 } これを返します。 } 保護された最終的な空隙adjustMarkers(INTデクリメント){ int型markedReaderIndex = this.markedReaderIndex。 IF(markedReaderIndex <=デクリメント){ this.markedReaderIndex = 0; int型markedWriterIndex = this.markedWriterIndex。 IF(markedWriterIndex <=デクリメント){ this.markedWriterIndex = 0; }他{ this.markedWriterIndex = markedWriterIndex - デクリメント。 } }他{ this.markedReaderIndex = markedReaderIndex - デクリメント。 markedWriterIndex - =デクリメント。 } }
ソースコード解析AbstractReferenceCountedByteBuf
从名字看出该类主要对引用进行计数,类似于JVM 内存回收的对象引用计数器,用于跟踪对象的分配和销毁,做自动内存回收。
パブリック抽象クラスAbstractReferenceCountedByteBufはAbstractByteBufを{拡張します //セキュリティスレッドを確保するために、CAS操作をアトミッククラスを使用します プライベート静的最終AtomicIntegerFieldUpdater <AbstractReferenceCountedByteBuf> refCntUpdater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class、 "REFCNT"); プライベート静的最終長いREFCNT_FIELD_OFFSET。 静的{ 長いrefCntFieldOffset = -1; {試します IF(PlatformDependent.hasUnsafe()){ refCntFieldOffset = PlatformDependent.objectFieldOffset( AbstractReferenceCountedByteBuf.class.getDeclaredField( "REFCNT")); } }キャッチ(ThrowableをT){ //無視 } REFCNT_FIELD_OFFSET = refCntFieldOffset。 } @SuppressWarnings( "FieldMayBeFinal") プライベート揮発int型REFCNT = 1; @オーバーライド 公共最終ブール放出(){ ために (;;) { int型REFCNT = this.refCnt。 IF(REFCNT == 0){ 新しいIllegalReferenceCountException(0、-1)投げます。 } IF(refCntUpdater.compareAndSet(この、REFCNT、REFCNT - 1)){ IF(REFCNT == 1){ DEALLOCATE(); trueを返します。 } falseを返します。 } } } @オーバーライド {)(保持ByteBuf公衆 ために (;;) { int型REFCNT = this.refCnt。 IF(REFCNT == 0){ 新しいIllegalReferenceCountException(0、1)を投げます。 } IF(REFCNT == Integer.MAX_VALUEの){ 新しいIllegalReferenceCountExceptionを投げる(Integer.MAX_VALUEで、1); } // CAS操作 IF(refCntUpdater.compareAndSet(この、REFCNT、REFCNT + 1)){ ブレーク; } } これを返します。 } ....
这个类有三个重要的字段,一个原子类用于多线程操作,保证线程安全。REFCNT_FIELD_OFFSET 是一个内存偏移量,用于标识 refCnt字段在AbstractReferenceCountedByteBuf这个类
的内存地址,最后一个refCnt 是用 volatile 修饰的变量,保存对象应用次数。
ソースコード解析ByteBuf UnpooledHeapByteBuf非メモリセルスタックメモリ
パブリッククラスUnpooledHeapByteBufはAbstractReferenceCountedByteBufを{延び //メモリ割り当て 民間最終ByteBufAllocatorのアロケーション; //バイトバッファ プライベートバイト[]配列。 //役割とJDKのByteBufferの変換 民間のByteBuffer tmpNioBuf。 ... プライベートINT GetBytesメソッド(int型のインデックス、GatheringByteChannelうち、int型の長さ、ブール内部)はIOExceptionが{スロー ensureAccessible(); ByteBuffer tmpBuf; //操作に使用tmpNioBufフィールド自体を返し、そうUnpooledHeapByteBufはJDK ByteBuffに基づいて延長されます。 IF(内部){ tmpBuf = internalNioBuffer()。 }他{ tmpBuf = ByteBuffer.wrap(アレイ) } out.write返す((のByteBuffer)tmpBuf.clear()位置(インデックス).limit(指標+長さ)。)。 } @オーバーライド 公共のint readBytes(GatheringByteChannelうち、int型の長さ)は、IOExceptionが{スロー checkReadableBytes(長さ)。 INT readBytes = GetBytesメソッド(readerIndex、アウト、長さ、TRUE); readerIndex + = readBytes。 readBytesを返します。 }
概要
文章主要介绍netty buffer 相关的知识,主要是父类方法和 unpooled 相关的实现。
参考資料
- "ネッティーDefinitive Guideの"