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
一般狀況下,當對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)則用於實現動態擴展,後面會詳細介紹其源碼。
方法名稱 | 返回值 | 功能說明 | 拋出異常 |
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 |
方法名稱 | 返回值 | 功能說明 | 拋出異常 |
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 |
調用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 |
方法名稱 | 返回值 | 功能說明 |
discardReadBytes() | ByteBuf | 釋放0到readerIndex之間已經讀取的空間;同時複製readerIndex和writerIndex之間的數據到0到writerIndex-readerIndex之間;修改readerIndex和writerIndex的值。該操做會發生字節數據的內存複製,頻繁調用會致使性能降低。此外,相比其餘java對象,緩衝區的分配和釋放是個耗時的操做,緩衝區的動態擴張須要進行進行字節數據的複製,也是耗時的操做,所以應儘可能提升緩衝區的重用率 |
discardSomeReadBytes() | ByteBuf | 功能和discardReadBytes()類似,不一樣之處在於可定製要釋放的空間,依賴於具體實現 |
clear() | ByteBuf | 與JDK 的ByteBuffer clear操做相同,該操做不會清空緩衝區內容自己,其主要是爲了操做位置指針,將readerIndex和writerIndex重置爲0 |
當對緩衝區進行讀寫操做時,可能須要對以前的操做進行回滾。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 |
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 |
當經過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 |
除順序讀寫以外,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