文档章节

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

AbeJeffrey
 AbeJeffrey
发布于 2016/09/04 21:53
字数 4413
阅读 3418
收藏 2

ByteBuf功能原理

ByteBuf是一个byte数组的缓冲区,通过两个位置指针完成缓冲区的读写操作,读操作使用readerIndex,写操作使用writeIndex。

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:

+-------------------+---------------------+
|   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。

//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操作都需要进行可写空间校验,这导致了代冗余。

为了解决这个问题,ByteBuf对write方法进行了封装,由write操作负责进行剩余可用空间的校验,当空间不足时,由ByteBuf自动进行动态扩展(不超过maxCapacity),使用者无需关心底层的校验和动态扩展细节。

源码如下:

    @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

© 著作权归作者所有

AbeJeffrey
粉丝 43
博文 43
码字总数 116095
作品 0
杭州
高级程序员
私信 提问
深入研究Netty框架之ByteBuf类继承结构

ByteBuf类继承关系图如下: ReferenceCounted:对象引用计数器,初始化ReferenceCounted对象时,引用数量refCnt为1,调用retain()可增加refCnt,release()用于减少refCnt。refCnt为1时,说明...

AbeJeffrey
2016/09/06
1K
0
《深入探索Netty原理及源码分析》文集小结

写在2017年末尾,翻看文集的第一篇文章已经是三个月前的事了,也没想过这文集会写那么久,这么慢。。。 Netty文集中的文章主要都是我学习过程的笔记,写博客的主要目的是为了通过输出来倒逼输...

tomas家的小拨浪鼓
2017/12/30
0
0
从零开始学netty——第一个netty程序

说在前面的事 自己学习用netty之前有很多的疑惑,这里先把自己的疑惑与答案写出来,希望可以帮到有同样疑惑的朋友。 问题:netty版本的选择,3,4,5。 答案:3和4的改动挺大,但是4和5的不大...

xpbob
2018/04/26
459
1
Netty 4.0 源码分析(四):ByteBuf

Netty是基于流的消息传递机制。Netty框架中,所有消息的传输都依赖于ByteBuf接口,ByteBuf是Netty NIO框架中的缓冲区。ByteBuf接口可以理解为一般的Byte数组,不过Netty对Byte进行了封装,增...

GreenDay
2014/09/13
1K
0
网络编程懒人入门(五):快速理解为什么说UDP有时比TCP更有优势

本文观点仅作参考,请根据自已系统的应用场景合理地选择数据传输层协议即可,无需盲目崇拜大牛言论。 1、前言 对于即时通讯开者新手来说,在开始着手编写IM或消息推送系统的代码前,最头疼的...

JackJiang2011
2017/12/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【TencentOS tiny】深度源码分析(4)——消息队列

消息队列 在前一篇文章中【TencentOS tiny学习】源码分析(3)——队列 我们描述了TencentOS tiny的队列实现,同时也点出了TencentOS tiny的队列是依赖于消息队列的,那么我们今天来看看消息...

杰杰1号
4分钟前
1
0
Hive

这就是那个 JAVA 类 package cn.itcast.bigdata;import java.util.HashMap;import org.apache.hadoop.hive.ql.exec.UDF;public class PhoneNbrToArea extends UDF{privat......

Garphy
4分钟前
2
0
Springboot开发,第二天

SpringBoot学习,第二天 目录:1、Springboot整合Listener 2、Springboot访问静态资源 3、异常处理 4、热部署 一、SpringBoot整合Listener 两种方式完成组件的注册 1、通过注解扫描完成组件的...

有一个小阿飞
8分钟前
3
0
BeginnersBook Perl 教程

来源:ApacheCN BeginnersBook 翻译项目 译者:飞龙 协议:CC BY-NC-SA 4.0 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 请您勇敢地去翻译和改进翻译。虽然我们追求卓越,但我们并...

ApacheCN_飞龙
20分钟前
2
0
我的Java秋招面经大合集

阿里面经 阿里中间件研发面经 蚂蚁金服研发面经 岗位是研发工程师,直接找蚂蚁金服的大佬进行内推。 我参与了阿里巴巴中间件部门的提前批面试,一共经历了四次面试,拿到了口头offer。 然后我...

Java技术江湖
25分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部