欢迎您的访问
专注架构,Java,数据结构算法,Python技术分享

Netty(一):ByteBuf 篇之 ByteBuf 内部结构与 API 学习

1、原生 ByteBuffer、ByteBuf 内部结构设计

首先我们来回顾一下 java.nio.ByteBuffe r的内部结构设计。

ByteBuffer 内部持有一个 byte[] bt, 再加上 position、limit、capacity、mark 四个属性。

  • position
    当前可用操作的位置,调用 get() 方法,返回 bt[postion] 处的值,如果是调用 put 方法,将数据放入 bt[position] 的位置。
  • limit
    可读或可写的最大索引。
  • capacity
    最大容量,ByteBuffer 对象一旦创建,不能修改 capacity 属性。
  • mark
    用来标记当前位置,以便可用回退到该位置,默认为 undefind。

下面主要举例说明一下 ByteBuffer 的存储。

    ByteBuffer bf = ByteBuffer.alloct(10);
    bf.put( (byte)"h" );
    bf.put( (byte)"e" );
    bf.put( (byte)"l" );
    bf.put( (byte)"l" );
    bf.put( (byte)"o" );

将产生下图的结构:

2020010910010\_1.png

那我们怎么从这个 ByteBuffer 中读取数据呢?如果调用 get 方法将会读出位置为5的数据,无法读取到 hello, 需要将 ByteBuffer 翻转,从写模式切换到读模式。

ByteBuffer 提供了一个方法 flip 方法,翻转缓存区,其如下如下:

    bf.limit = bf.postion;
    bf.positioin = 0;

关于 ByteBuffer 更多知识,建议下载一本电子书(《java NIO 中文版》)

为了简化缓存区的读、写的操作, Netty ByteBuf 引入了两个位置属性,readIndex,writeIndex,来取代position。这样就不需要在读、写之间切换了。其结构设计如下:

2020010910010\_2.png

  • discardable bytes
    已读的内容。
  • readable bytes
    暂未读的内容。
  • writable bytes
    区域是可以写区域。

discardable bytes 区域是可以使用 discardReadBytes() 方法,将 readables bytes 丢弃,然后将 readable bytes 移动到 byte 数组的开始处,这也相当于 ByteBuffer的compact()方法(压缩),但这会产生缓存区内部元素的移动,会降低性能。

2020010910010\_3.png

由于引入了 writerIndex, limit 属性不需要了。

上述简单介绍了ByteBuffer、ByteBuf 数据的内部存储,这对我们正确使用缓存区至关重要。

2、ByteBuf类图与常用API学习

2.1 ByteBuf 类图

2020010910010\_4.png

现阶段主要描述一下主要类的作用。

  1. AbstractReferenceCountedByteBuf
    不难理解,ByteBuf,一个最最重要的方面就是内存的管理,涉及到创建、重复利用、回收等方方面面,而AbstractReferenceCountedByteBuf 就是使用引用计数来管理内存的回收。
  2. CompositeByteBuf ByteBuf
    组合ByteBuf,比如一个协议分为协议头,协议主体,这两部分都是一个单独的 ByteBuf, 在处理这两个ByteBuf 时,然后需要将这个数据在网络上传输。我们的常规做法,是需要创建一个更大的 ByteBuf, 然后将 head,body 的内容写入新创建的ByteBuf, CompositeByteBuf 就是用来解决这个,提供一个类似数据库视图这样的概念。
  3. PooledByteBuf
    池化的 ByteBuf, ByteBuf 对象池.
  4. UnpooledDirectByteBuf
    非池化的直接内存(不占用 JVM 的堆内存,也叫堆外内存)。
  5. UnpooledHeapByteBuf
    非池化的堆内存(占用JVM堆内存)。

2.2 ByteBuf 主要 API

顺序读写API(read、write) 相关API,会移动对应的读写指针,而随机访问API(get、put)相关API并不会改变读写指针。

2.2.1 顺序读API

    /**
         * Gets a boolean at the current {@code readerIndex} and increases
         * the {@code readerIndex} by {@code 1} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 1}
         */
        public abstract boolean readBoolean();

        /**
         * Gets a byte at the current {@code readerIndex} and increases
         * the {@code readerIndex} by {@code 1} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 1}
         */
        public abstract byte  readByte();

        /**
         * Gets an unsigned byte at the current {@code readerIndex} and increases
         * the {@code readerIndex} by {@code 1} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 1}
         */
        public abstract short readUnsignedByte();

        /**
         * Gets a 16-bit short integer at the current {@code readerIndex}
         * and increases the {@code readerIndex} by {@code 2} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 2}
         */
        public abstract short readShort();

        /**
         * Gets an unsigned 16-bit short integer at the current {@code readerIndex}
         * and increases the {@code readerIndex} by {@code 2} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 2}
         */
        public abstract int   readUnsignedShort();

        /**
         * Gets a 24-bit medium integer at the current {@code readerIndex}
         * and increases the {@code readerIndex} by {@code 3} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 3}
         */
        public abstract int   readMedium();

        /**
         * Gets an unsigned 24-bit medium integer at the current {@code readerIndex}
         * and increases the {@code readerIndex} by {@code 3} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 3}
         */
        public abstract int   readUnsignedMedium();

        /**
         * Gets a 32-bit integer at the current {@code readerIndex}
         * and increases the {@code readerIndex} by {@code 4} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 4}
         */
        public abstract int   readInt();

        /**
         * Gets an unsigned 32-bit integer at the current {@code readerIndex}
         * and increases the {@code readerIndex} by {@code 4} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 4}
         */
        public abstract long  readUnsignedInt();

        /**
         * Gets a 64-bit integer at the current {@code readerIndex}
         * and increases the {@code readerIndex} by {@code 8} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 8}
         */
        public abstract long  readLong();

        /**
         * Gets a 2-byte UTF-16 character at the current {@code readerIndex}
         * and increases the {@code readerIndex} by {@code 2} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 2}
         */
        public abstract char  readChar();

        /**
         * Gets a 32-bit floating point number at the current {@code readerIndex}
         * and increases the {@code readerIndex} by {@code 4} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 4}
         */
        public abstract float readFloat();

        /**
         * Gets a 64-bit floating point number at the current {@code readerIndex}
         * and increases the {@code readerIndex} by {@code 8} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.readableBytes} is less than {@code 8}
         */
        public abstract double readDouble();

        /**
         * Transfers this buffer's data to a newly created buffer starting at
         * the current {@code readerIndex} and increases the {@code readerIndex}
         * by the number of the transferred bytes (= {@code length}).
         * The returned buffer's {@code readerIndex} and {@code writerIndex} are
         * {@code 0} and {@code length} respectively.
         *
         * @param length the number of bytes to transfer
         *
         * @return the newly created buffer which contains the transferred bytes
         *
         * @throws IndexOutOfBoundsException
         *         if {@code length} is greater than {@code this.readableBytes}
         */
        public abstract ByteBuf readBytes(int length);

        /**
         * Returns a new slice of this buffer's sub-region starting at the current
         * {@code readerIndex} and increases the {@code readerIndex} by the size
         * of the new slice (= {@code length}).
         *
         * @param length the size of the new slice
         *
         * @return the newly created slice
         *
         * @throws IndexOutOfBoundsException
         *         if {@code length} is greater than {@code this.readableBytes}
         */
        public abstract ByteBuf readSlice(int length);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the current {@code readerIndex} until the destination becomes
         * non-writable, and increases the {@code readerIndex} by the number of the
         * transferred bytes.  This method is basically same with
         * {@link #readBytes(ByteBuf, int, int)}, except that this method
         * increases the {@code writerIndex} of the destination by the number of
         * the transferred bytes while {@link #readBytes(ByteBuf, int, int)}
         * does not.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code dst.writableBytes} is greater than
         *            {@code this.readableBytes}
         */
        public abstract ByteBuf readBytes(ByteBuf dst);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the current {@code readerIndex} and increases the {@code readerIndex}
         * by the number of the transferred bytes (= {@code length}).  This method
         * is basically same with {@link #readBytes(ByteBuf, int, int)},
         * except that this method increases the {@code writerIndex} of the
         * destination by the number of the transferred bytes (= {@code length})
         * while {@link #readBytes(ByteBuf, int, int)} does not.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code length} is greater than {@code this.readableBytes} or
         *         if {@code length} is greater than {@code dst.writableBytes}
         */
        public abstract ByteBuf readBytes(ByteBuf dst, int length);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the current {@code readerIndex} and increases the {@code readerIndex}
         * by the number of the transferred bytes (= {@code length}).
         *
         * @param dstIndex the first index of the destination
         * @param length   the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code dstIndex} is less than {@code 0},
         *         if {@code length} is greater than {@code this.readableBytes}, or
         *         if {@code dstIndex + length} is greater than
         *            {@code dst.capacity}
         */
        public abstract ByteBuf readBytes(ByteBuf dst, int dstIndex, int length);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the current {@code readerIndex} and increases the {@code readerIndex}
         * by the number of the transferred bytes (= {@code dst.length}).
         *
         * @throws IndexOutOfBoundsException
         *         if {@code dst.length} is greater than {@code this.readableBytes}
         */
        public abstract ByteBuf readBytes(byte[] dst);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the current {@code readerIndex} and increases the {@code readerIndex}
         * by the number of the transferred bytes (= {@code length}).
         *
         * @param dstIndex the first index of the destination
         * @param length   the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code dstIndex} is less than {@code 0},
         *         if {@code length} is greater than {@code this.readableBytes}, or
         *         if {@code dstIndex + length} is greater than {@code dst.length}
         */
        public abstract ByteBuf readBytes(byte[] dst, int dstIndex, int length);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the current {@code readerIndex} until the destination's position
         * reaches its limit, and increases the {@code readerIndex} by the
         * number of the transferred bytes.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code dst.remaining()} is greater than
         *            {@code this.readableBytes}
         */
        public abstract ByteBuf readBytes(ByteBuffer dst);

        /**
         * Transfers this buffer's data to the specified stream starting at the
         * current {@code readerIndex}.
         *
         * @param length the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if {@code length} is greater than {@code this.readableBytes}
         * @throws IOException
         *         if the specified stream threw an exception during I/O
         */
        public abstract ByteBuf readBytes(OutputStream out, int length) throws IOException;

        /**
         * Transfers this buffer's data to the specified stream starting at the
         * current {@code readerIndex}.
         *
         * @param length the maximum number of bytes to transfer
         *
         * @return the actual number of bytes written out to the specified channel
         *
         * @throws IndexOutOfBoundsException
         *         if {@code length} is greater than {@code this.readableBytes}
         * @throws IOException
         *         if the specified channel threw an exception during I/O
         */
        public abstract int  readBytes(GatheringByteChannel out, int length) throws IOException;

对于上面的方法,我挑如下三个进行重点说明一下,其他的类似:

  • public abstract ByteBuf readBytes(byte[] dst)
    从 ByteBuf 缓存区中读取 dst.length 个字节到 dst 目标数组中,返回当前的 ByteBuf, 这是级联设计风格,如果 ByteBuf 可剩余可读字节小于 dst.length,则抛出异常。
  • public abstract ByteBuf readBytes(int length)
    从 ByteBuf 缓存区读取 length 个字节到新创建的 ByteBuf, 注意返回的 ByteBuf 是先创建的,这不是级联设计风格。
  • public abstract ByteBuf readBytes(ByteBuf dst)
    从 ByteBuf 缓存区读取 ds t可写字节长度到 dst 中,返回的 ByteBuf 是级联风格设计,如果 dst 的可剩余写长度大于操作的缓存区时,将抛出异常。
  • public abstract ByteBuf readSlice(int length)
    从 ButeBuf 缓存区读取 length 个字节到 ByteBuf 中,这里的 ByteBuf 是原 ByteBuf 的视图,独立的 readIndex, writerIndex。

2.2.2 顺序写API

    /**
         * Sets the specified boolean at the current {@code writerIndex}
         * and increases the {@code writerIndex} by {@code 1} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.writableBytes} is less than {@code 1}
         */
        public abstract ByteBuf writeBoolean(boolean value);

        /**
         * Sets the specified byte at the current {@code writerIndex}
         * and increases the {@code writerIndex} by {@code 1} in this buffer.
         * The 24 high-order bits of the specified value are ignored.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.writableBytes} is less than {@code 1}
         */
        public abstract ByteBuf writeByte(int value);

        /**
         * Sets the specified 16-bit short integer at the current
         * {@code writerIndex} and increases the {@code writerIndex} by {@code 2}
         * in this buffer.  The 16 high-order bits of the specified value are ignored.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.writableBytes} is less than {@code 2}
         */
        public abstract ByteBuf writeShort(int value);

        /**
         * Sets the specified 24-bit medium integer at the current
         * {@code writerIndex} and increases the {@code writerIndex} by {@code 3}
         * in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.writableBytes} is less than {@code 3}
         */
        public abstract ByteBuf writeMedium(int   value);

        /**
         * Sets the specified 32-bit integer at the current {@code writerIndex}
         * and increases the {@code writerIndex} by {@code 4} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.writableBytes} is less than {@code 4}
         */
        public abstract ByteBuf writeInt(int   value);

        /**
         * Sets the specified 64-bit long integer at the current
         * {@code writerIndex} and increases the {@code writerIndex} by {@code 8}
         * in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.writableBytes} is less than {@code 8}
         */
        public abstract ByteBuf writeLong(long  value);

        /**
         * Sets the specified 2-byte UTF-16 character at the current
         * {@code writerIndex} and increases the {@code writerIndex} by {@code 2}
         * in this buffer.  The 16 high-order bits of the specified value are ignored.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.writableBytes} is less than {@code 2}
         */
        public abstract ByteBuf writeChar(int value);

        /**
         * Sets the specified 32-bit floating point number at the current
         * {@code writerIndex} and increases the {@code writerIndex} by {@code 4}
         * in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.writableBytes} is less than {@code 4}
         */
        public abstract ByteBuf writeFloat(float value);

        /**
         * Sets the specified 64-bit floating point number at the current
         * {@code writerIndex} and increases the {@code writerIndex} by {@code 8}
         * in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code this.writableBytes} is less than {@code 8}
         */
        public abstract ByteBuf writeDouble(double value);

        /**
         * Transfers the specified source buffer's data to this buffer starting at
         * the current {@code writerIndex} until the source buffer becomes
         * unreadable, and increases the {@code writerIndex} by the number of
         * the transferred bytes.  This method is basically same with
         * {@link #writeBytes(ByteBuf, int, int)}, except that this method
         * increases the {@code readerIndex} of the source buffer by the number of
         * the transferred bytes while {@link #writeBytes(ByteBuf, int, int)}
         * does not.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code src.readableBytes} is greater than
         *            {@code this.writableBytes}
         */
        public abstract ByteBuf writeBytes(ByteBuf src);

        /**
         * Transfers the specified source buffer's data to this buffer starting at
         * the current {@code writerIndex} and increases the {@code writerIndex}
         * by the number of the transferred bytes (= {@code length}).  This method
         * is basically same with {@link #writeBytes(ByteBuf, int, int)},
         * except that this method increases the {@code readerIndex} of the source
         * buffer by the number of the transferred bytes (= {@code length}) while
         * {@link #writeBytes(ByteBuf, int, int)} does not.
         *
         * @param length the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if {@code length} is greater than {@code this.writableBytes} or
         *         if {@code length} is greater then {@code src.readableBytes}
         */
        public abstract ByteBuf writeBytes(ByteBuf src, int length);

        /**
         * Transfers the specified source buffer's data to this buffer starting at
         * the current {@code writerIndex} and increases the {@code writerIndex}
         * by the number of the transferred bytes (= {@code length}).
         *
         * @param srcIndex the first index of the source
         * @param length   the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code srcIndex} is less than {@code 0},
         *         if {@code srcIndex + length} is greater than
         *            {@code src.capacity}, or
         *         if {@code length} is greater than {@code this.writableBytes}
         */
        public abstract ByteBuf writeBytes(ByteBuf src, int srcIndex, int length);

        /**
         * Transfers the specified source array's data to this buffer starting at
         * the current {@code writerIndex} and increases the {@code writerIndex}
         * by the number of the transferred bytes (= {@code src.length}).
         *
         * @throws IndexOutOfBoundsException
         *         if {@code src.length} is greater than {@code this.writableBytes}
         */
        public abstract ByteBuf writeBytes(byte[] src);

        /**
         * Transfers the specified source array's data to this buffer starting at
         * the current {@code writerIndex} and increases the {@code writerIndex}
         * by the number of the transferred bytes (= {@code length}).
         *
         * @param srcIndex the first index of the source
         * @param length   the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code srcIndex} is less than {@code 0},
         *         if {@code srcIndex + length} is greater than
         *            {@code src.length}, or
         *         if {@code length} is greater than {@code this.writableBytes}
         */
        public abstract ByteBuf writeBytes(byte[] src, int srcIndex, int length);

        /**
         * Transfers the specified source buffer's data to this buffer starting at
         * the current {@code writerIndex} until the source buffer's position
         * reaches its limit, and increases the {@code writerIndex} by the
         * number of the transferred bytes.
         *
         * @throws IndexOutOfBoundsException
         *         if {@code src.remaining()} is greater than
         *            {@code this.writableBytes}
         */
        public abstract ByteBuf writeBytes(ByteBuffer src);

        /**
         * Transfers the content of the specified stream to this buffer
         * starting at the current {@code writerIndex} and increases the
         * {@code writerIndex} by the number of the transferred bytes.
         *
         * @param length the number of bytes to transfer
         *
         * @return the actual number of bytes read in from the specified stream
         *
         * @throws IndexOutOfBoundsException
         *         if {@code length} is greater than {@code this.writableBytes}
         * @throws IOException
         *         if the specified stream threw an exception during I/O
         */
        public abstract int  writeBytes(InputStream in, int length) throws IOException;

        /**
         * Transfers the content of the specified channel to this buffer
         * starting at the current {@code writerIndex} and increases the
         * {@code writerIndex} by the number of the transferred bytes.
         *
         * @param length the maximum number of bytes to transfer
         *
         * @return the actual number of bytes read in from the specified channel
         *
         * @throws IndexOutOfBoundsException
         *         if {@code length} is greater than {@code this.writableBytes}
         * @throws IOException
         *         if the specified channel threw an exception during I/O
         */
        public abstract int  writeBytes(ScatteringByteChannel in, int length) throws IOException;

        /**
         * Fills this buffer with <tt>NUL (0x00)</tt> starting at the current
         * {@code writerIndex} and increases the {@code writerIndex} by the
         * specified {@code length}.
         *
         * @param length the number of <tt>NUL</tt>s to write to the buffer
         *
         * @throws IndexOutOfBoundsException
         *         if {@code length} is greater than {@code this.writableBytes}
         */
        public abstract ByteBuf writeZero(int length);

重点强调一下如下方法,其他的类似。

  • public abstract ByteBuf writeBytes(byte[] src)
    将字节数组 src 全部写入到缓存区中,如果 src.length 大于 ByteBuf 可写区域的话,会抛出异常。

2.2.3 随机读API

    /**
         * Gets a boolean at the specified absolute (@code index) in this buffer.
         * This method does not modify the {@code readerIndex} or {@code writerIndex}
         * of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 1} is greater than {@code this.capacity}
         */
        public abstract boolean getBoolean(int index);

        /**
         * Gets a byte at the specified absolute {@code index} in this buffer.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 1} is greater than {@code this.capacity}
         */
        public abstract byte  getByte(int index);

        /**
         * Gets an unsigned byte at the specified absolute {@code index} in this
         * buffer.  This method does not modify {@code readerIndex} or
         * {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 1} is greater than {@code this.capacity}
         */
        public abstract short getUnsignedByte(int index);

        /**
         * Gets a 16-bit short integer at the specified absolute {@code index} in
         * this buffer.  This method does not modify {@code readerIndex} or
         * {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 2} is greater than {@code this.capacity}
         */
        public abstract short getShort(int index);

        /**
         * Gets an unsigned 16-bit short integer at the specified absolute
         * {@code index} in this buffer.  This method does not modify
         * {@code readerIndex} or {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 2} is greater than {@code this.capacity}
         */
        public abstract int getUnsignedShort(int index);

        /**
         * Gets a 24-bit medium integer at the specified absolute {@code index} in
         * this buffer.  This method does not modify {@code readerIndex} or
         * {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 3} is greater than {@code this.capacity}
         */
        public abstract int   getMedium(int index);

        /**
         * Gets an unsigned 24-bit medium integer at the specified absolute
         * {@code index} in this buffer.  This method does not modify
         * {@code readerIndex} or {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 3} is greater than {@code this.capacity}
         */
        public abstract int   getUnsignedMedium(int index);

        /**
         * Gets a 32-bit integer at the specified absolute {@code index} in
         * this buffer.  This method does not modify {@code readerIndex} or
         * {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 4} is greater than {@code this.capacity}
         */
        public abstract int   getInt(int index);

        /**
         * Gets an unsigned 32-bit integer at the specified absolute {@code index}
         * in this buffer.  This method does not modify {@code readerIndex} or
         * {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 4} is greater than {@code this.capacity}
         */
        public abstract long  getUnsignedInt(int index);

        /**
         * Gets a 64-bit long integer at the specified absolute {@code index} in
         * this buffer.  This method does not modify {@code readerIndex} or
         * {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 8} is greater than {@code this.capacity}
         */
        public abstract long  getLong(int index);

        /**
         * Gets a 2-byte UTF-16 character at the specified absolute
         * {@code index} in this buffer.  This method does not modify
         * {@code readerIndex} or {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 2} is greater than {@code this.capacity}
         */
        public abstract char  getChar(int index);

        /**
         * Gets a 32-bit floating point number at the specified absolute
         * {@code index} in this buffer.  This method does not modify
         * {@code readerIndex} or {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 4} is greater than {@code this.capacity}
         */
        public abstract float getFloat(int index);

        /**
         * Gets a 64-bit floating point number at the specified absolute
         * {@code index} in this buffer.  This method does not modify
         * {@code readerIndex} or {@code writerIndex} of this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 8} is greater than {@code this.capacity}
         */
        public abstract double getDouble(int index);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the specified absolute {@code index} until the destination becomes
         * non-writable.  This method is basically same with
         * {@link #getBytes(int, ByteBuf, int, int)}, except that this
         * method increases the {@code writerIndex} of the destination by the
         * number of the transferred bytes while
         * {@link #getBytes(int, ByteBuf, int, int)} does not.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * the source buffer (i.e. {@code this}).
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + dst.writableBytes} is greater than
         *            {@code this.capacity}
         */
        public abstract ByteBuf getBytes(int index, ByteBuf dst);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the specified absolute {@code index}.  This method is basically same
         * with {@link #getBytes(int, ByteBuf, int, int)}, except that this
         * method increases the {@code writerIndex} of the destination by the
         * number of the transferred bytes while
         * {@link #getBytes(int, ByteBuf, int, int)} does not.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * the source buffer (i.e. {@code this}).
         *
         * @param length the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0},
         *         if {@code index + length} is greater than
         *            {@code this.capacity}, or
         *         if {@code length} is greater than {@code dst.writableBytes}
         */
        public abstract ByteBuf getBytes(int index, ByteBuf dst, int length);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the specified absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex}
         * of both the source (i.e. {@code this}) and the destination.
         *
         * @param dstIndex the first index of the destination
         * @param length   the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0},
         *         if the specified {@code dstIndex} is less than {@code 0},
         *         if {@code index + length} is greater than
         *            {@code this.capacity}, or
         *         if {@code dstIndex + length} is greater than
         *            {@code dst.capacity}
         */
        public abstract ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the specified absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + dst.length} is greater than
         *            {@code this.capacity}
         */
        public abstract ByteBuf getBytes(int index, byte[] dst);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the specified absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex}
         * of this buffer.
         *
         * @param dstIndex the first index of the destination
         * @param length   the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0},
         *         if the specified {@code dstIndex} is less than {@code 0},
         *         if {@code index + length} is greater than
         *            {@code this.capacity}, or
         *         if {@code dstIndex + length} is greater than
         *            {@code dst.length}
         */
        public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length);

        /**
         * Transfers this buffer's data to the specified destination starting at
         * the specified absolute {@code index} until the destination's position
         * reaches its limit.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer while the destination's {@code position} will be increased.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + dst.remaining()} is greater than
         *            {@code this.capacity}
         */
        public abstract ByteBuf getBytes(int index, ByteBuffer dst);

        /**
         * Transfers this buffer's data to the specified stream starting at the
         * specified absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @param length the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + length} is greater than
         *            {@code this.capacity}
         * @throws IOException
         *         if the specified stream threw an exception during I/O
         */
        public abstract ByteBuf getBytes(int index, OutputStream out, int length) throws IOException;

        /**
         * Transfers this buffer's data to the specified channel starting at the
         * specified absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @param length the maximum number of bytes to transfer
         *
         * @return the actual number of bytes written out to the specified channel
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + length} is greater than
         *            {@code this.capacity}
         * @throws IOException
         *         if the specified channel threw an exception during I/O
         */
        public abstract int getBytes(int index, GatheringByteChannel out, int length) throws IOException;

重点解读如下API,其他类似。

  • public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length)
    从源 ByteBuf 的 index 处开始读 length 个字节到目标 byte 中,从 dstIndex 开始。

2.2.4 随机写API

    /**
         * Sets the specified boolean at the specified absolute {@code index} in this
         * buffer.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 1} is greater than {@code this.capacity}
         */
        public abstract ByteBuf setBoolean(int index, boolean value);

        /**
         * Sets the specified byte at the specified absolute {@code index} in this
         * buffer.  The 24 high-order bits of the specified value are ignored.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 1} is greater than {@code this.capacity}
         */
        public abstract ByteBuf setByte(int index, int value);

        /**
         * Sets the specified 16-bit short integer at the specified absolute
         * {@code index} in this buffer.  The 16 high-order bits of the specified
         * value are ignored.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 2} is greater than {@code this.capacity}
         */
        public abstract ByteBuf setShort(int index, int value);

        /**
         * Sets the specified 24-bit medium integer at the specified absolute
         * {@code index} in this buffer.  Please note that the most significant
         * byte is ignored in the specified value.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 3} is greater than {@code this.capacity}
         */
        public abstract ByteBuf setMedium(int index, int   value);

        /**
         * Sets the specified 32-bit integer at the specified absolute
         * {@code index} in this buffer.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 4} is greater than {@code this.capacity}
         */
        public abstract ByteBuf setInt(int index, int   value);

        /**
         * Sets the specified 64-bit long integer at the specified absolute
         * {@code index} in this buffer.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 8} is greater than {@code this.capacity}
         */
        public abstract ByteBuf setLong(int index, long  value);

        /**
         * Sets the specified 2-byte UTF-16 character at the specified absolute
         * {@code index} in this buffer.
         * The 16 high-order bits of the specified value are ignored.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 2} is greater than {@code this.capacity}
         */
        public abstract ByteBuf setChar(int index, int value);

        /**
         * Sets the specified 32-bit floating-point number at the specified
         * absolute {@code index} in this buffer.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 4} is greater than {@code this.capacity}
         */
        public abstract ByteBuf setFloat(int index, float value);

        /**
         * Sets the specified 64-bit floating-point number at the specified
         * absolute {@code index} in this buffer.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         {@code index + 8} is greater than {@code this.capacity}
         */
        public abstract ByteBuf setDouble(int index, double value);

        /**
         * Transfers the specified source buffer's data to this buffer starting at
         * the specified absolute {@code index} until the source buffer becomes
         * unreadable.  This method is basically same with
         * {@link #setBytes(int, ByteBuf, int, int)}, except that this
         * method increases the {@code readerIndex} of the source buffer by
         * the number of the transferred bytes while
         * {@link #setBytes(int, ByteBuf, int, int)} does not.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * the source buffer (i.e. {@code this}).
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + src.readableBytes} is greater than
         *            {@code this.capacity}
         */
        public abstract ByteBuf setBytes(int index, ByteBuf src);

        /**
         * Transfers the specified source buffer's data to this buffer starting at
         * the specified absolute {@code index}.  This method is basically same
         * with {@link #setBytes(int, ByteBuf, int, int)}, except that this
         * method increases the {@code readerIndex} of the source buffer by
         * the number of the transferred bytes while
         * {@link #setBytes(int, ByteBuf, int, int)} does not.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * the source buffer (i.e. {@code this}).
         *
         * @param length the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0},
         *         if {@code index + length} is greater than
         *            {@code this.capacity}, or
         *         if {@code length} is greater than {@code src.readableBytes}
         */
        public abstract ByteBuf setBytes(int index, ByteBuf src, int length);

        /**
         * Transfers the specified source buffer's data to this buffer starting at
         * the specified absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex}
         * of both the source (i.e. {@code this}) and the destination.
         *
         * @param srcIndex the first index of the source
         * @param length   the number of bytes to transfer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0},
         *         if the specified {@code srcIndex} is less than {@code 0},
         *         if {@code index + length} is greater than
         *            {@code this.capacity}, or
         *         if {@code srcIndex + length} is greater than
         *            {@code src.capacity}
         */
        public abstract ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length);

        /**
         * Transfers the specified source array's data to this buffer starting at
         * the specified absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + src.length} is greater than
         *            {@code this.capacity}
         */
        public abstract ByteBuf setBytes(int index, byte[] src);

        /**
         * Transfers the specified source array's data to this buffer starting at
         * the specified absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0},
         *         if the specified {@code srcIndex} is less than {@code 0},
         *         if {@code index + length} is greater than
         *            {@code this.capacity}, or
         *         if {@code srcIndex + length} is greater than {@code src.length}
         */
        public abstract ByteBuf setBytes(int index, byte[] src, int srcIndex, int length);

        /**
         * Transfers the specified source buffer's data to this buffer starting at
         * the specified absolute {@code index} until the source buffer's position
         * reaches its limit.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + src.remaining()} is greater than
         *            {@code this.capacity}
         */
        public abstract ByteBuf setBytes(int index, ByteBuffer src);

        /**
         * Transfers the content of the specified source stream to this buffer
         * starting at the specified absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @param length the number of bytes to transfer
         *
         * @return the actual number of bytes read in from the specified channel.
         *         {@code -1} if the specified channel is closed.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + length} is greater than {@code this.capacity}
         * @throws IOException
         *         if the specified stream threw an exception during I/O
         */
        public abstract int setBytes(int index, InputStream in, int length) throws IOException;

        /**
         * Transfers the content of the specified source channel to this buffer
         * starting at the specified absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @param length the maximum number of bytes to transfer
         *
         * @return the actual number of bytes read in from the specified channel.
         *         {@code -1} if the specified channel is closed.
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + length} is greater than {@code this.capacity}
         * @throws IOException
         *         if the specified channel threw an exception during I/O
         */
        public abstract int  setBytes(int index, ScatteringByteChannel in, int length) throws IOException;

        /**
         * Fills this buffer with <tt>NUL (0x00)</tt> starting at the specified
         * absolute {@code index}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         *
         * @param length the number of <tt>NUL</tt>s to write to the buffer
         *
         * @throws IndexOutOfBoundsException
         *         if the specified {@code index} is less than {@code 0} or
         *         if {@code index + length} is greater than {@code this.capacity}
         */
        public abstract ByteBuf setZero(int index, int length);

    1.2.2.5 ByteBuf复制相关API
    /**
         * Returns a copy of this buffer's readable bytes.  Modifying the content
         * of the returned buffer or this buffer does not affect each other at all.
         * This method is identical to {@code buf.copy(buf.readerIndex(), buf.readableBytes())}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         */
        public abstract ByteBuf copy();

        /**
         * Returns a copy of this buffer's sub-region.  Modifying the content of
         * the returned buffer or this buffer does not affect each other at all.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         */
        public abstract ByteBuf copy(int index, int length);

        /**
         * Returns a slice of this buffer's readable bytes. Modifying the content
         * of the returned buffer or this buffer affects each other's content
         * while they maintain separate indexes and marks.  This method is
         * identical to {@code buf.slice(buf.readerIndex(), buf.readableBytes())}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         */
        public abstract ByteBuf slice();

        /**
         * Returns a slice of this buffer's sub-region. Modifying the content of
         * the returned buffer or this buffer affects each other's content while
         * they maintain separate indexes and marks.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         */
        public abstract ByteBuf slice(int index, int length);

        /**
         * Returns a buffer which shares the whole region of this buffer.
         * Modifying the content of the returned buffer or this buffer affects
         * each other's content while they maintain separate indexes and marks.
         * This method is identical to {@code buf.slice(0, buf.capacity())}.
         * This method does not modify {@code readerIndex} or {@code writerIndex} of
         * this buffer.
         */
        public abstract ByteBuf duplicate();

需要说明的是,slice、duplicate 方法,返回的 ByteBuf 与原共享数据结构,只是单独维护 readIndex,writerIndex。copy 方法会创建不同的 byte[] 数组,相互之间不会影响。

2.2.7 ByteBuf mark,reset,clear 的 API

    /**
         * Sets the {@code readerIndex} and {@code writerIndex} of this buffer to
         * {@code 0}.
         * This method is identical to {@link #setIndex(int, int) setIndex(0, 0)}.
         * <p>
         * Please note that the behavior of this method is different
         * from that of NIO buffer, which sets the {@code limit} to
         * the {@code capacity} of the buffer.
         */
        public abstract ByteBuf clear();

        /**
         * Marks the current {@code readerIndex} in this buffer.  You can
         * reposition the current {@code readerIndex} to the marked
         * {@code readerIndex} by calling {@link #resetReaderIndex()}.
         * The initial value of the marked {@code readerIndex} is {@code 0}.
         */
        public abstract ByteBuf markReaderIndex();

        /**
         * Repositions the current {@code readerIndex} to the marked
         * {@code readerIndex} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the current {@code writerIndex} is less than the marked
         *         {@code readerIndex}
         */
        public abstract ByteBuf resetReaderIndex();

        /**
         * Marks the current {@code writerIndex} in this buffer.  You can
         * reposition the current {@code writerIndex} to the marked
         * {@code writerIndex} by calling {@link #resetWriterIndex()}.
         * The initial value of the marked {@code writerIndex} is {@code 0}.
         */
        public abstract ByteBuf markWriterIndex();

        /**
         * Repositions the current {@code writerIndex} to the marked
         * {@code writerIndex} in this buffer.
         *
         * @throws IndexOutOfBoundsException
         *         if the current {@code readerIndex} is greater than the marked
         *         {@code writerIndex}
         */
        public abstract ByteBuf resetWriterIndex();

        /**
         * Discards the bytes between the 0th index and {@code readerIndex}.
         * It moves the bytes between {@code readerIndex} and {@code writerIndex}
         * to the 0th index, and sets {@code readerIndex} and {@code writerIndex}
         * to {@code 0} and {@code oldWriterIndex - oldReaderIndex} respectively.
         * <p>
         * Please refer to the class documentation for more detailed explanation.
         */
        public abstract ByteBuf discardReadBytes();

        /**
         * Similar to {@link ByteBuf#discardReadBytes()} except that this method might discard
         * some, all, or none of read bytes depending on its internal implementation to reduce
         * overall memory bandwidth consumption at the cost of potentially additional memory
         * consumption.
         */
        public abstract ByteBuf discardSomeReadBytes();

2.2.8 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);

看了这么多的分类的API,貌似没有看到创建相关的API,比如java.nio.ByteBuffer的 allocateDirect(int capacity) 等方法。原因是Netty 对 ByteBuf 的创建单独抽象成一个体系 ByteBufAllocator,包括了直接内存、堆内存,池化的 ByteBuf,这些将在源码分析ByteBuf 相关类时重点去学习。


来源:https://blog.csdn.net/prestigeding/article/details/53977445

赞(0) 打赏
版权归原创作者所有,任何形式转载请联系作者;码农code之路 » Netty(一):ByteBuf 篇之 ByteBuf 内部结构与 API 学习

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏