深刻研究Netty框架之ByteBuf功能原理及源碼分析

ByteBuf功能原理

ByteBuf是一個byte數組的緩衝區,經過兩個位置指針完成緩衝區的讀寫操做,讀操做使用readerIndex,寫操做使用writeIndex。java

readerIndex和writeIndex初始取值均爲0,寫入數據,writeIndex增長;讀取數據則readerIndex增長。0~readerIndex之間的數據是已經讀取的,調用discardReadBytes()可釋放這部分空間,其做用相似於JDK ByteBuffer的compact()方法;readerIndex~writeIndex之間的數據是可讀取的,等價於ByteBuffer position和limit之間的數據;writeIndex和capacity之間的空間是可寫入的,等價於ByteBuffer limit和capacity之間的可用空間;調用clear()可重置readerIndex和writeIndex爲0,但該操做不會清理buffer中的內容。數據庫

初始分配的ByteBuf:數組

+-------------------------------------------------------+
|                writable bytes                         |
+-------------------------------------------------------+
|                                                       |
0 = readerIndex = writerIndex                       capacity

寫入N個字節後的ByteBuf:網絡

+-------------------------------------+------------------+
|       readable bytes                |  writable bytes  |
|       (CONTENT)                     |                  |
+-------------------------------------+------------------+
|                                     |                  |
0 = readerIndex                N = writerIndex    <=  capacity

讀取M(<=N)個字節後的ByteBuf:框架

+-------------------+------------------+------------------+
| discardable bytes |  readable bytes  |  writable bytes  |
|                   |     (CONTENT)    |                  |
+-------------------+------------------+------------------+
|                   |                  |                  |
0          M  = readerIndex  <=    N = writerIndex  <= capacity

調用discardReadBytes()方法以後的ByteBuf:ide

+-------------------+---------------------+
|   readable bytes  |  writable bytes     |
+-------------------+---------------------+
|                   |                     |
0 = readerIndex   N-M = writerIndex  <= capacity

調用clear()方法以後的ByteBuf:性能

+-------------------------------------------------------+
|                writable bytes                         |
+-------------------------------------------------------+
|                                                       |
0 = readerIndex = writerIndex                       capacity

ByteBuf 動態擴展

一般狀況下,當對JDK ByteBuffer進行put操做時,若是緩衝區可寫空間不夠,就會拋出BufferOverflowException異常。爲了不這個問題,在進行put操做時,須要對可寫空間進行判斷,若是剩餘可寫空間不足,須要建立一個新ByteBuffer,並將以前ByteBuffer的內容複製到新建立的ByteBuffer中,而後釋放老的ByteBuffer。this

//needSize爲須要寫入的字節數
if(this.buffer.remaining()<needSize){
    int realAllocateSize=needSize>128 ? needSize:128;
    ByteBuffer newBuffer=ByteBuffer.allocate(this.buffer.capacity()+realAllocateSize);
    this.buffer.flip();
    newBuffer.put(this.buffer);
    this.buffer=newBuffer;
}

爲防止ByteBuffer溢出,每次進行put操做都須要進行可寫空間校驗,這致使了代冗餘。spa

爲了解決這個問題,ByteBuf對write方法進行了封裝,由write操做負責進行剩餘可用空間的校驗,當空間不足時,由ByteBuf自動進行動態擴展(不超過maxCapacity),使用者無需關心底層的校驗和動態擴展細節。.net

源碼以下:

@Override
    public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
        ensureWritable(length);
        setBytes(writerIndex, src, srcIndex, length);
        writerIndex += length;
        return this;
    }

當執行writeBytes時,先調用ensureWritable(length)進行可寫空間的校驗。

@Override
    public 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));
        }

        // Normalize the current capacity to the power of 2.
        int newCapacity = calculateNewCapacity(writerIndex + minWritableBytes);

        // Adjust to the new capacity.
        capacity(newCapacity);
        return this;
    }

當須要寫入的字節數大於緩衝區最大可寫字節數時,ByteBuf自動進行動態擴展。calculateNewCapacity(writerIndex + minWritableBytes)方法用於計算緩衝區新的容量,capacity(newCapacity)則用於實現動態擴展,後面會詳細介紹其源碼。

ByteBuf 主要API

順序讀操做(read)

方法名稱 返回值 功能說明 拋出異常
readBoolean() boolean

從readerIndex開始讀取1字節的數據

throws IndexOutOfBoundsException

readableBytes<1

readByte() byte 從readerIndex開始讀取1字節的數據

throws IndexOutOfBoundsException

readableBytes<1

readUnsignedByte() short 從readerIndex開始讀取1字節的數據(無符號字節值)

throws IndexOutOfBoundsException:

readableBytes<1

readShort() short 從readerIndex開始讀取16位的短整形值

throws IndexOutOfBoundsException:

readableBytes<2

readUnsignedShort() int 從readerIndex開始讀取16位的無符號短整形值

throws IndexOutOfBoundsException:

readableBytes<2

readMedium() int 從readerIndex開始讀取24位的整形值,(該類型並不是java基本類型,一般不用)

throws IndexOutOfBoundsException:

readableBytes<3

readUnsignedMedium() int 從readerIndex開始讀取24位的無符號整形值,(該類型並不是java基本類型,一般不用)

throws IndexOutOfBoundsException:

readableBytes<3

readInt() int 從readerIndex開始讀取32位的整形值

throws IndexOutOfBoundsException:

readableBytes<4

readUnsignedInt() long 從readerIndex開始讀取32位的無符號整形值

throws IndexOutOfBoundsException:

readableBytes<4

readLong() long 從readerIndex開始讀取64位的整形值

throws IndexOutOfBoundsException:

readableBytes<8

readChar() char 從readerIndex開始讀取2字節的字符值

throws IndexOutOfBoundsException:

readableBytes<2

readFloat() float 從readerIndex開始讀取32位的浮點值

throws IndexOutOfBoundsException:

readableBytes<4

readDouble() double 從readerIndex開始讀取64位的浮點值

throws IndexOutOfBoundsException:

readableBytes<8

readBytes(int length) ByteBuf

將當前ByteBuf中的數據讀取到新建立的ByteBuf中,從readerIndex開始讀取length字節的數據。返回的ByteBuf readerIndex 爲0,writeIndex爲length。

throws IndexOutOfBoundsException:

readableBytes<length

readSlice(int length) ByteBuf 返回當前ByteBuf新建立的子區域,子區域和原ByteBuf共享緩衝區的內容,但獨立維護本身的readerIndex和writeIndex,新建立的子區域readerIndex 爲0,writeIndex爲length。

throws IndexOutOfBoundsException:

readableBytes<length

readBytes(ByteBuf dst) ByteBuf

將當前ByteBuf中的數據讀取到目標ByteBuf (dst)中,從當前ByteBuf readerIndex開始讀取,直到目標ByteBuf無可寫空間,從目標ByteBuf writeIndex開始寫入數據。讀取完成後,當前ByteBuf的readerIndex+=讀取的字節數。目標ByteBuf的writeIndex+=讀取的字節數。

throws IndexOutOfBoundsException:

this.readableBytes<dst.writableBytes

readBytes(ByteBuf dst, int length) ByteBuf 將當前ByteBuf中的數據讀取到目標ByteBuf (dst)中,從當前ByteBuf readerIndex開始讀取,長度爲length,從目標ByteBuf writeIndex開始寫入數據。讀取完成後,當前ByteBuf的readerIndex+=length,目標ByteBuf的writeIndex+=length

throws IndexOutOfBoundsException:

this.readableBytes<length or

dst.writableBytes<length

readBytes(ByteBuf dst, int dstIndex, int length) ByteBuf 將當前ByteBuf中的數據讀取到目標ByteBuf (dst)中,從readerIndex開始讀取,長度爲length,從目標ByteBuf dstIndex開始寫入數據。讀取完成後,當前ByteBuf的readerIndex+=length,目標ByteBuf的writeIndex+=length

throws IndexOutOfBoundsException:

dstIndex<0 or

this.readableBytes<length or

dst.capacity<dstIndex + length

readBytes(byte[] dst) ByteBuf 將當前ByteBuf中的數據讀取到byte數組dst中,從當前ByteBuf readerIndex開始讀取,讀取長度爲dst.length,從byte數組dst索引0處開始寫入數據。

throws IndexOutOfBoundsException:

this.readableBytes<dst.length

readBytes(byte[] dst, int dstIndex, int length) ByteBuf 將當前ByteBuf中的數據讀取到byte數組dst中,從當前ByteBuf readerIndex開始讀取,讀取長度爲length,從byte數組dst索引dstIndex處開始寫入數據。

throws IndexOutOfBoundsException:

dstIndex<0 or 

this.readableBytes<length or 

dst.length<dstIndex + length

readBytes(ByteBuffer dst) ByteBuf 將當前ByteBuf中的數據讀取到ByteBuffer dst中,從當前ByteBuf readerIndex開始讀取,直到dst的位置指針到達ByteBuffer 的limit。讀取完成後,當前ByteBuf的readerIndex+=dst.remaining()

throws IndexOutOfBoundsException:

this.readableBytes<dst.remaining() 

readBytes(OutputStream out, int length) ByteBuf 將當前ByteBuf readerIndex讀取數據到輸出流OutputStream中,讀取的字節長度爲length

throws IndexOutOfBoundsException:

this.readableBytes<length 

throws  IOException

readBytes(GatheringByteChannel out, int length)  int 將當前ByteBuf readerIndex讀取數到GatheringByteChannel 中,寫入out的最大字節長度爲length。GatheringByteChannel爲非阻塞Channel,調用其write方法不可以保存將所有須要寫入的數據均寫入成功,存在半包問題。所以其寫入的數據長度爲【0,length】,若是操做成功,readerIndex+=實際寫入的字節數,返回實際寫入的字節數

throws IndexOutOfBoundsException:

this.readableBytes<length 

throws  IOException

順序寫操做(write)

方法名稱 返回值 功能說明 拋出異常
writeBoolean(boolean value) ByteBuf

將value寫入到當前ByteBuf中。寫入成功,writeIndex+=1

throws IndexOutOfBoundsException:

this.writableBytes<1

writeByte(int value) ByteBuf 將value寫入到當前ByteBuf中。寫入成功,writeIndex+=1

throws IndexOutOfBoundsException:

this.writableBytes<1

writeShort(int value) ByteBuf 將value寫入到當前ByteBuf中。寫入成功,writeIndex+=2

throws IndexOutOfBoundsException:

this.writableBytes<2

writeMedium(int   value) ByteBuf 將value寫入到當前ByteBuf中。寫入成功,writeIndex+=3

throws IndexOutOfBoundsException:

this.writableBytes<3

writeInt(int   value) ByteBuf 將value寫入到當前ByteBuf中。寫入成功,writeIndex+=4

throws IndexOutOfBoundsException:

this.writableBytes<4

writeLong(long  value) ByteBuf 將value寫入到當前ByteBuf中。寫入成功,writeIndex+=8

throws IndexOutOfBoundsException:

this.writableBytes<8

writeChar(int value) ByteBuf 將value寫入到當前ByteBuf中。寫入成功,writeIndex+=2

throws IndexOutOfBoundsException:

this.writableBytes<2

writeFloat(float value) ByteBuf 將value寫入到當前ByteBuf中。寫入成功,writeIndex+=4

throws IndexOutOfBoundsException:

this.writableBytes<4

writeDouble(double value) ByteBuf 將value寫入到當前ByteBuf中。寫入成功,writeIndex+=8

throws IndexOutOfBoundsException:

this.writableBytes<8

writeBytes(ByteBuf src) ByteBuf 將源ByteBuf src中從readerIndex開始的全部可讀字節寫入到當前ByteBuf。從當前ByteBuf writeIndex寫入數據。寫入成功,writeIndex+=src.readableBytes

throws IndexOutOfBoundsException:

this.writableBytes<src.readableBytes

writeBytes(ByteBuf src, int length) ByteBuf 將源ByteBuf src中從readerIndex開始,長度length的可讀字節寫入到當前ByteBuf。從當前ByteBuf writeIndex寫入數據。寫入成功,writeIndex+=length

throws IndexOutOfBoundsException:

this.writableBytes<length or

src.readableBytes<length

writeBytes(ByteBuf src, int srcIndex, int length) ByteBuf 將源ByteBuf src中從srcIndex開始,長度length的可讀字節寫入到當前ByteBuf。從當前ByteBuf writeIndex寫入數據。寫入成功,writeIndex+=length

throws IndexOutOfBoundsException:

srcIndex<0  or

this.writableBytes<length or

src.capacity<srcIndex + length

writeBytes(byte[] src) ByteBuf 將源字節數組src中全部可讀字節寫入到當前ByteBuf。從當前ByteBuf writeIndex寫入數據。寫入成功,writeIndex+=src.length

throws IndexOutOfBoundsException:

this.writableBytes<src.length

writeBytes(byte[] src, int srcIndex, int length) ByteBuf 將源字節數組src中srcIndex開始,長度爲length可讀字節寫入到當前ByteBuf。從當前ByteBuf writeIndex寫入數據。寫入成功,writeIndex+=length

throws IndexOutOfBoundsException:

srcIndex<0 or

this.writableBytes<src.length or

src.length<srcIndex + length

writeBytes(ByteBuffer mignsrc) ByteBuf 將源ByteBuffer src中全部可讀字節寫入到當前ByteBuf。從當前ByteBuf writeIndex寫入數據。寫入成功,writeIndex+=src.remaining()

throws IndexOutOfBoundsException:

this.writableBytes<src.remaining()

writeBytes(InputStream in, int length) int 將源InputStream in中的內容寫入到當前ByteBuf,寫入的最大長度爲length,實際寫入的字節數可能少於length。從當前ByteBuf writeIndex寫入數據。寫入成功,writeIndex+=實際寫入的字節數。返回實際寫入的字節數

throws IndexOutOfBoundsException:

this.writableBytes<length

writeBytes(ScatteringByteChannel in, int length) int 將源ScatteringByteChannel in中的內容寫入到當前ByteBuf,寫入的最大長度爲length,實際寫入的字節數可能少於length。從當前ByteBuf writeIndex寫入數據。寫入成功,writeIndex+=實際寫入的字節數。返回實際寫入的字節數

throws IndexOutOfBoundsException:

this.writableBytes<length

writeZero(int length) ByteBuf 將當前緩衝區的內容填充爲NUL(0x00),當前ByteBuf writeIndex寫入數據。寫入成功,writeIndex+=length

throws IndexOutOfBoundsException:

this.writableBytes<length

readerIndex 和 writeIndex

調用ByteBuf的read操做時,從readerIndex開始讀取數據,調用ByteBuf的write操做時,從writeIndex開始寫入數據,readerIndex和writeInde關係以下:

+-------------------+------------------+------------------+
| discardable bytes |  readable bytes  |  writable bytes  |
|                   |     (CONTENT)    |                  |
+-------------------+------------------+------------------+
|                   |                  |                  |
0      <=      readerIndex   <=   writerIndex    <=    capacity
方法名稱 返回值 功能說明 拋出異常
readerIndex() int 返回當前ByteBuf的readerIndex  
readerIndex(int readerIndex) ByteBuf 修改當前ByteBuf的readerIndex

throws IndexOutOfBoundsException

this.writerIndex<readerIndex

writerIndex() int 返回當前ByteBuf的writeIndex  
writerIndex(int writerIndex) ByteBuf 修改當前ByteBuf的writeIndex

throws IndexOutOfBoundsException

writeIndex<this.readerIndex or

this.capacity<writerIndex

readableBytes() int

獲取當前ByteBuf的可讀字節數

this.writerIndex -this.readerIndex

 
writableBytes() int

獲取當前ByteBuf的可寫字節數

this.capacity - this.writerIndex

 
setIndex(int readerIndex, int writerIndex) ByteBuf 快捷設置當前ByteBuf的readerIndex和writerIndex

throws IndexOutOfBoundsException

readerIndex<0 or

this.writerIndex<readerIndex or

this.capacity<writerIndex

skipBytes(int length) ByteBuf 更新當前ByteBuf的readerIndex,更新後將跳過length字節的數據讀取。

throws IndexOutOfBoundsException

this.readableBytes<length

釋放空間和clear操做

方法名稱 返回值 功能說明
 discardReadBytes() ByteBuf 釋放0到readerIndex之間已經讀取的空間;同時複製readerIndex和writerIndex之間的數據到0到writerIndex-readerIndex之間;修改readerIndex和writerIndex的值。該操做會發生字節數據的內存複製,頻繁調用會致使性能降低。此外,相比其餘java對象,緩衝區的分配和釋放是個耗時的操做,緩衝區的動態擴張須要進行進行字節數據的複製,也是耗時的操做,所以應儘可能提升緩衝區的重用率
discardSomeReadBytes() ByteBuf 功能和discardReadBytes()類似,不一樣之處在於可定製要釋放的空間,依賴於具體實現
clear() ByteBuf 與JDK 的ByteBuffer clear操做相同,該操做不會清空緩衝區內容自己,其主要是爲了操做位置指針,將readerIndex和writerIndex重置爲0

mark和rest

當對緩衝區進行讀寫操做時,可能須要對以前的操做進行回滾。ByteBuf可經過調用mark操做將當前的位置指針備份到mark變量中,調用rest操做後,從新將指針的當前位置恢復爲備份在mark變量的值。ByteBuf主要有如下相關方法:

markReaderIndex():將當前的readerIndex備份到markedReaderIndex中;

resetReaderIndex():將當前的readerIndex重置爲markedReaderIndex的值;

markWriterIndex() :將當前的writerIndex備份到markedWriterIndex中;

resetWriterIndex():將當前的writerIndex重置爲markedWriterIndex的值;

相關源碼:

@Override
    public ByteBuf markReaderIndex() {
        markedReaderIndex = readerIndex;
        return this;
    }

    @Override
    public ByteBuf resetReaderIndex() {
        readerIndex(markedReaderIndex);
        return this;
    }

    @Override
    public ByteBuf markWriterIndex() {
        markedWriterIndex = writerIndex;
        return this;
    }

    @Override
    public ByteBuf resetWriterIndex() {
        writerIndex = markedWriterIndex;
        return this;
    }

查找操做

方法名稱 返回值 功能說明 拋出異常
indexOf(int fromIndex, int toIndex, byte value) int 從當前ByteBuf中查找首次出現value的位置,fromIndex<=查找範圍<toIndex;查找成功返回位置索引,不然返回-1  
bytesBefore(byte value) int 從當前ByteBuf中查找首次出現value的位置,readerIndex<=查找範圍<writerIndex;查找成功返回位置索引,不然返回-1  
bytesBefore(int length, byte value) int 從當前ByteBuf中查找首次出現value的位置,readerIndex<=查找範圍<readerIndex+length;查找成功返回位置索引,不然返回-1

IndexOutOfBoundsException:

this.readableBytes<length

bytesBefore(int index, int length, byte value) int 從當前ByteBuf中查找首次出現value的位置,index<=查找範圍<index+length;查找成功返回位置索引,不然返回-1

IndexOutOfBoundsException:

this.readableBytes<index+length

forEachByte(ByteBufProcessor processor); int  遍歷當前ByteBuf的可讀字節數組,與ByteBufProcessor中設置的查找條件進行比對,從readerIndex開始遍歷直到writerIndex。若是知足條件,返回位置索引,不然返回-1  
forEachByte(int index, int length, ByteBufProcessor processor)   遍歷當前ByteBuf的可讀字節數組,與ByteBufProcessor中設置的查找條件進行比對,從index開始遍歷直到index+length。若是知足條件,返回位置索引,不然返回-1  
forEachByteDesc(ByteBufProcessor processor)   逆序遍歷當前ByteBuf的可讀字節數組,與ByteBufProcessor中設置的查找條件進行比對,從writerIndex-1開始遍歷直到readerIndex。若是知足條件,返回位置索引,不然返回-1  
forEachByteDesc(int index, int length, ByteBufProcessor processor)   逆序遍歷當前ByteBuf的可讀字節數組,與ByteBufProcessor中設置的查找條件進行比對,從index+length-1開始遍歷直到index。若是知足條件,返回位置索引,不然返回-1  

Buffer視圖

Derived Buffers相似於數據庫視圖,ByteBuf提供了多個接口用於建立某個ByteBuf的視圖或者複製ByteBuf。主要操做以下:

方法名稱 返回值 功能說明
duplicate() ByteBuf 返回當前ByteBuf的複製對象,複製後的ByteBuf對象與當前ByteBuf對象共享緩衝區的內容,可是維護本身獨立的readerIndex和writerIndex。該操做不修改原ByteBuf的readerIndex和writerIndex。
copy() ByteBuf 從當前ByteBuf複製一個新的ByteBuf對象,複製的新對象緩衝區的內容和索引均是獨立的。該操做不修改原ByteBuf的readerIndex和writerIndex。(複製readerIndex到writerIndex之間的內容,其餘屬性與原ByteBuf相同,如maxCapacity,ByteBufAllocator)
copy(int index, int length) ByteBuf 從當前ByteBuf 指定索引index開始,字節長度爲length,複製一個新的ByteBuf對象,複製的新對象緩衝區的內容和索引均是獨立的。該操做不修改原ByteBuf的readerIndex和writerIndex。(其餘屬性與原ByteBuf相同,,如maxCapacity,ByteBufAllocator)
slice() ByteBuf 返回當前ByteBuf的可讀子區域,起始位置從readerIndex到writerIndex,返回的ByteBuf對象與當前ByteBuf對象共享緩衝區的內容,可是維護本身獨立的readerIndex和writerIndex。該操做不修改原ByteBuf的readerIndex和writerIndex。返回ByteBuf對象的長度爲readableBytes()
slice(int index, int length) ByteBuf 返回當前ByteBuf的可讀子區域,起始位置從index到index+length,返回的ByteBuf對象與當前ByteBuf對象共享緩衝區的內容,可是維護本身獨立的readerIndex和writerIndex。該操做不修改原ByteBuf的readerIndex和writerIndex。返回ByteBuf對象的長度爲length

轉換爲JDK ByteBuffer

當經過NIO的SocketChannel進行網絡讀寫時,操做的對象爲JDK的ByteBuffer,所以須在接口層支持netty ByteBuf到JDK的ByteBuffer的相互轉換。

方法名稱 返回值 功能說明 拋出異常
nioBuffer() ByteBuffer 將當前ByteBuf的可讀緩衝區(readerIndex到writerIndex之間的內容)轉換爲ByteBuffer,二者共享共享緩衝區的內容。對ByteBuffer的讀寫操做不會影響ByteBuf的讀寫索引。注意:ByteBuffer沒法感知ByteBuf的動態擴展操做。ByteBuffer的長度爲readableBytes() UnsupportedOperationException
nioBuffer(int index, int length) ByteBuffer 將當前ByteBuf的可讀緩衝區(index到index+length之間的內容)轉換爲ByteBuffer,二者共享共享緩衝區的內容。對ByteBuffer的讀寫操做不會影響ByteBuf的讀寫索引。注意:ByteBuffer沒法感知ByteBuf的動態擴展操做。ByteBuffer的長度爲length UnsupportedOperationException

隨機讀寫(set和get)

除順序讀寫以外,ByteBuf還支持隨機讀寫,其最大的區別在於可隨機指定讀寫的索引位置。

關於隨機讀寫的API這裏再也不詳述。不管set或get,執行前都會進行索引和長度的合法性驗證,此外,set操做不一樣於write的是不支持動態擴展。部分源碼:

@Override
    public ByteBuf getBytes(int index, byte[] dst) {
        getBytes(index, dst, 0, dst.length);
        return this;
    }
    //
    @Override
    public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
        checkDstIndex(index, length, dstIndex, dst.length);
        System.arraycopy(array, index, dst, dstIndex, length);
        return this;
    }

    protected final void checkDstIndex(int index, int length, int dstIndex, int dstCapacity) {
        checkIndex(index, length);
        if (dstIndex < 0 || dstIndex > dstCapacity - length) {
            throw new IndexOutOfBoundsException(String.format(
                    "dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dstCapacity));
        }
    }

    protected final void checkIndex(int index, int fieldLength) {
        ensureAccessible();
        if (fieldLength < 0) {
            throw new IllegalArgumentException("length: " + fieldLength + " (expected: >= 0)");
        }
        if (index < 0 || index > capacity() - fieldLength) {
            throw new IndexOutOfBoundsException(String.format(
                    "index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity()));
        }
    }
@Override
    public ByteBuf setByte(int index, int value) {
        checkIndex(index);
        _setByte(index, value);
        return this;
    }
    //索引合法性驗證
    protected final void checkIndex(int index) {
        ensureAccessible();
        if (index < 0 || index >= capacity()) {
            throw new IndexOutOfBoundsException(String.format(
                    "index: %d (expected: range(0, %d))", index, capacity()));
        }
    }
    //確認ByteBuf對象可訪問,引用計數器不爲0
    protected final void ensureAccessible() {
        if (refCnt() == 0) {
            throw new IllegalReferenceCountException(0);
        }
    }
    //UnpooledHeapByteBuf 實現
    @Override
    protected void _setByte(int index, int value) {
        array[index] = (byte) value;
    }

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

相關文章
相關標籤/搜索