其他分享
首页 > 其他分享> > ByteBuf 内部结构设计

ByteBuf 内部结构设计

作者:互联网

一、首先介绍下 ReferenceCounted 接口

public interface ReferenceCounted {
    /**
     * 返回对象的引用数量,如果返回0,表示这个对象已经被释放
     */
    int refCnt();

    /**
     * 引用计数加 1
     */
    ReferenceCounted retain();

    /**
     * 引用计数加 increment
     */
    ReferenceCounted retain(int increment);

    /**
     * 引用计数减 1,如果引用计数为0,则会释放这个对象
     *
     * @return 当且仅当引用计数变为0,并且这个对象已经被释放时返回true
     */
    boolean release();

    /**
     * 引用计数减 decrement,如果引用计数为0,则会释放这个对象
     * @return 当且仅当引用计数变为0,并且这个对象已经被释放时返回true
     */
    boolean release(int decrement);
}

二、ByteBuf介绍

1、ByteBuf实现了ReferenceCounted接口,ByteBuf提供随机和顺序两种方式读取一个或者多个字节序列。

(1)Random Access Indexing

ByteBuf提供类似于原始数组的方式,起始索引是0,结束索引是capacity-1。

(2)Sequential Access Indexing 

ByteBuf 提供两个指针来支持顺序读和顺序写操作。用readIndex来支持读操作,writeIndex来支持写操作。下图展示readIndex 和 writeIndex对ByteBuf进行分段

discardable bytes

这部分表示已经读过的区域,初始为0,最大值为writeIndex,执行读操作时这部分内容会相应的增加。可以通过调用 discardReadBytes 方法来回收这部分区域,达到获取更多writeable byte空间的效果

执行discardReadBytes之前如下图

执行discardReadBytes之后如下图

readable bytes

内容实际存储区域。执行以start或者skip开始的方法时,如果没有足够的内容供读取,会抛出 IndexOutOfBoundsException 异常

writeable bytes

可写区间

(3)Clearing the buffer index

可以调用clear方法来把readIndex 和 writeIndex的值重置为0,但是clear方法不会清空内容。

ByteBuf顺序读和顺序写、随机读和随机写的API都比较简单,此处不介绍。介绍下 ByteBuf 与 java nio 原生 ByteBuffer 转换


/**
     * Returns the maximum number of NIO {@link ByteBuffer}s that consist this buffer.  Note that {@link #nioBuffers()}
     * or {@link #nioBuffers(int, int)} might return a less number of {@link ByteBuffer}s.
     *
     * @return {@code -1} if this buffer has no underlying {@link ByteBuffer}.
     *         the number of the underlying {@link ByteBuffer}s if this buffer has at least one underlying
     *         {@link ByteBuffer}.  Note that this method does not return {@code 0} to avoid confusion.
     *
     * @see #nioBuffer()
     * @see #nioBuffer(int, int)
     * @see #nioBuffers()
     * @see #nioBuffers(int, int)
     */
    public abstract int nioBufferCount();
 
    /**
     * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}.  The returned buffer
     * shares the content with this buffer, while changing the position and limit of the returned
     * NIO buffer does not affect the indexes and marks of this buffer.  This method is identical
     * to {@code buf.nioBuffer(buf.readerIndex(), buf.readableBytes())}.  This method does not
     * modify {@code readerIndex} or {@code writerIndex} of this buffer.  Please note that the
     * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic
     * buffer and it adjusted its capacity.
     *
     * @throws UnsupportedOperationException
     *         if this buffer cannot create a {@link ByteBuffer} that shares the content with itself
     *
     * @see #nioBufferCount()
     * @see #nioBuffers()
     * @see #nioBuffers(int, int)
     */
    public abstract ByteBuffer nioBuffer();
 
    /**
     * Exposes this buffer's sub-region as an NIO {@link ByteBuffer}.  The returned buffer
     * shares the content with this buffer, while changing the position and limit of the returned
     * NIO buffer does not affect the indexes and marks of this buffer.  This method does not
     * modify {@code readerIndex} or {@code writerIndex} of this buffer.  Please note that the
     * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic
     * buffer and it adjusted its capacity.
     *
     * @throws UnsupportedOperationException
     *         if this buffer cannot create a {@link ByteBuffer} that shares the content with itself
     *
     * @see #nioBufferCount()
     * @see #nioBuffers()
     * @see #nioBuffers(int, int)
     */
    public abstract ByteBuffer nioBuffer(int index, int length);
 
    /**
     * Internal use only: Exposes the internal NIO buffer.
     */
    public abstract ByteBuffer internalNioBuffer(int index, int length);
 
    /**
     * Exposes this buffer's readable bytes as an NIO {@link ByteBuffer}'s.  The returned buffer
     * shares the content with this buffer, while changing the position and limit of the returned
     * NIO buffer does not affect the indexes and marks of this buffer. This method does not
     * modify {@code readerIndex} or {@code writerIndex} of this buffer.  Please note that the
     * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic
     * buffer and it adjusted its capacity.
     *
     *
     * @throws UnsupportedOperationException
     *         if this buffer cannot create a {@link ByteBuffer} that shares the content with itself
     *
     * @see #nioBufferCount()
     * @see #nioBuffer()
     * @see #nioBuffer(int, int)
     */
    public abstract ByteBuffer[] nioBuffers();
 
    /**
     * Exposes this buffer's bytes as an NIO {@link ByteBuffer}'s for the specified index and length
     * The returned buffer shares the content with this buffer, while changing the position and limit
     * of the returned NIO buffer does not affect the indexes and marks of this buffer. This method does
     * not modify {@code readerIndex} or {@code writerIndex} of this buffer.  Please note that the
     * returned NIO buffer will not see the changes of this buffer if this buffer is a dynamic
     * buffer and it adjusted its capacity.
     *
     * @throws UnsupportedOperationException
     *         if this buffer cannot create a {@link ByteBuffer} that shares the content with itself
     *
     * @see #nioBufferCount()
     * @see #nioBuffer()
     * @see #nioBuffer(int, int)
     */
    public abstract ByteBuffer[] nioBuffers(int index, int length);

ByteBuf中不存在 java.nio.ByteBuffer的 allocateDirect(int capacity) 等方法。原因是Netty 对 ByteBuf 的创建单独抽象成一个体系 ByteBufAllocator,包括了直接内存、堆内存,池化的 ByteBuf,后续不断学习,不断补充。

标签:ByteBuf,buffer,see,int,内部结构,link,ByteBuffer,设计,NIO
来源: https://blog.csdn.net/ycb1914845451/article/details/110942860