- 浏览: 978866 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
netty 通道接口定义:http://donald-draper.iteye.com/blog/2392740
netty 抽象通道初始化:http://donald-draper.iteye.com/blog/2392801
netty 抽象Unsafe定义:http://donald-draper.iteye.com/blog/2393053
netty 通道Outbound缓冲区:http://donald-draper.iteye.com/blog/2393098
netty 抽象通道后续:http://donald-draper.iteye.com/blog/2393166
netty 抽象nio通道:http://donald-draper.iteye.com/blog/2393269
netty 抽象nio字节通道:http://donald-draper.iteye.com/blog/2393323
netty 抽象nio消息通道:http://donald-draper.iteye.com/blog/2393364
netty NioServerSocketChannel解析:http://donald-draper.iteye.com/blog/2393443
netty 通道配置接口定义:http://donald-draper.iteye.com/blog/2393484
netty 默认通道配置初始化:http://donald-draper.iteye.com/blog/2393504
netty 默认通道配置后续:http://donald-draper.iteye.com/blog/2393510
引言
前面两篇文章我们看了通道配置,先来简单回顾一下:
默认通道配置内部主要是配置消息大小估算器,字节buf分配器,接收字节buf分配器等属性。默认ServerSocket通道配置,与ServerSocket相关的配置委托给ServerSocket的相关方法,其他委托给父类默认通道配置。默认Socket通道配置,与Socket相关的配置委托给Socket的相关方法,其他委托给父类默认通道配置。
在上面的两篇文章中,我们有说过字节buf分配器,字节buf分配器可以创建direct和heap类型的ByteBuf,接下来的文章先看一下
字节buf接口的定义,再看字节buf分配器非配的direct和heap类型的字节buf实现。先从字节buf接口定义:
再看字节buf接口定义前,来看一下引用计数器接口的定义:
从上面可以看出,对象引用计数器ReferenceCounted,主要记录对象的引用数量,当引用数量为0时,表示可以回收对象,在调试模式下,如果发现对象出现内存泄漏,可以用touch方法记录操作的相关信息,通过ResourceLeakDetector获取操作的相关信息,以便分析内存泄漏的原因。
再来看字节buf的接口定义:
总结:
对象引用计数器ReferenceCounted,主要记录对象的引用数量,当引用数量为0时,表示可以回收对象,在调试模式下,如果发现对象出现内存泄漏,可以用touch方法记录操作的相关信息,通过ResourceLeakDetector获取操作的相关信息,以便分析内存泄漏的原因。
字节缓存ByteBuf继承了对象引用计数器ReferenceCounted,拥有一个最大容量限制,如果用户尝试用 #capacity(int)和 #ensureWritable(int)方法,增加buf容量超过最大容量,将会抛出非法参数异常;字节buf有两个索引,一个为读索引readerIndex,一个为写索引writerIndex,读索引不能大于写索引,写索引不能小于读索引,buf可读字节数为writerIndex - readerIndex,buf可写字节数为capacity - writerIndex,buf可写的最大字节数为maxCapacity - writerIndex;
可以使用markReader/WriterIndex标记当前buf读写索引位置,resetReader/WriterIndex方法可以重回先前标记的索引位置;
当内存空间负载过度时,我们可以使用discardReadBytes丢弃一些数据,以节省空间;
我们可以使用ensureWritable检测当buf是否有足够的空间写数据;
提供了getBytes方法,可以将buf中的数据转移到目的ByteBuf,Byte数组,Nio字节buf ByteBuffer,OutputStream,聚集字节通道
GatheringByteChannel和文件通道FileChannel中,这些方法不会修改当前buf读写索引,具体是否修改目的对象索引或位置,见java doc 描述。
提供了setBytes方法,可以将源ByteBuf,Byte数组,Nio字节buf ByteBuffer,InputputStream,分散字节通道ScatteringByteChannel和文件通道FileChannel中的数据转移到当前buf中,这些方法不会修改当前buf的读写索引,至于源对象索引或位置,见java doc 描述。
提供了readBytes方法,可以将buf中的数据转移到目的ByteBuf,Byte数组,Nio字节buf ByteBuffer,OutputStream,聚集字节通道GatheringByteChannel和文件通道FileChannel中,这些方法具体会会修改当前buf读索引,至于会不会修改源对象索引或位置,见java doc 描述。
提供了writeBytes方法,可以将源ByteBuf,Byte数组,Nio字节buf ByteBuffer,
InputputStream,分散字节通道ScatteringByteChannel和文件通道FileChannel中的数据写到当前buf中,这些方法会修改当前buf的写索引,至于会不会修改源对象索引或位置,见java
doc 描述。
set*原始类型方法不会修改读写索引;
get*原始类型方法不会修改读写索引;
write*原始类型方法会修改写索引;
read*原始类型方法,会修改读索引;
字节buf中的set/get*方法不会修改当前buf的读写索引,而write*修改写索引,read*会修改读索引;
提供了copy,slice和retainSlice,duplicate和retainedDuplicate方法,用于拷贝,切割,复制当前buf数据,retained*方法会增加buf的引用计数器;
提供nioBuffer和nioBuffers方法,用于包装当前buf可读数据为java nio ByteBuffer和ByteBuffer数组。
附:
下面是字节buf的get*原始类型方法的定义,简单看一下:
下面的方法不会修改读写索引
下面一些set*原始类型方法从索引index开始,设置原始类型,不会修改读写索引
以下一些read*原始类型方法,会修改读索引
下面是一些write*原始类型的方法,会增加写索引
下面是一些字节搜索定位方法:
//ByteProcessor
netty 抽象通道初始化:http://donald-draper.iteye.com/blog/2392801
netty 抽象Unsafe定义:http://donald-draper.iteye.com/blog/2393053
netty 通道Outbound缓冲区:http://donald-draper.iteye.com/blog/2393098
netty 抽象通道后续:http://donald-draper.iteye.com/blog/2393166
netty 抽象nio通道:http://donald-draper.iteye.com/blog/2393269
netty 抽象nio字节通道:http://donald-draper.iteye.com/blog/2393323
netty 抽象nio消息通道:http://donald-draper.iteye.com/blog/2393364
netty NioServerSocketChannel解析:http://donald-draper.iteye.com/blog/2393443
netty 通道配置接口定义:http://donald-draper.iteye.com/blog/2393484
netty 默认通道配置初始化:http://donald-draper.iteye.com/blog/2393504
netty 默认通道配置后续:http://donald-draper.iteye.com/blog/2393510
引言
前面两篇文章我们看了通道配置,先来简单回顾一下:
默认通道配置内部主要是配置消息大小估算器,字节buf分配器,接收字节buf分配器等属性。默认ServerSocket通道配置,与ServerSocket相关的配置委托给ServerSocket的相关方法,其他委托给父类默认通道配置。默认Socket通道配置,与Socket相关的配置委托给Socket的相关方法,其他委托给父类默认通道配置。
在上面的两篇文章中,我们有说过字节buf分配器,字节buf分配器可以创建direct和heap类型的ByteBuf,接下来的文章先看一下
字节buf接口的定义,再看字节buf分配器非配的direct和heap类型的字节buf实现。先从字节buf接口定义:
public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
再看字节buf接口定义前,来看一下引用计数器接口的定义:
package io.netty.util; /** * A reference-counted object that requires explicit deallocation. * * When a new {@link ReferenceCounted} is instantiated, it starts with the reference count of {@code 1}. * {@link #retain()} increases the reference count, and {@link #release()} decreases the reference count. * If the reference count is decreased to {@code 0}, the object will be deallocated explicitly, and accessing * the deallocated object will usually result in an access violation. * * * If an object that implements {@link ReferenceCounted} is a container of other objects that implement * {@link ReferenceCounted}, the contained objects will also be released via {@link #release()} when the container's * reference count becomes 0. * */ public interface ReferenceCounted { /** * Returns the reference count of this object. If {@code 0}, it means this object has been deallocated. 返回对象的引用计数器,为0,表示对象可以被回收 */ int refCnt(); /** * Increases the reference count by {@code 1}. 对象引用计数器自增1 */ ReferenceCounted retain(); /** * Increases the reference count by the specified {@code increment}. 增加引用计数器,增量为increment */ ReferenceCounted retain(int increment); /** * Records the current access location of this object for debugging purposes. * If this object is determined to be leaked, the information recorded by this operation will be provided to you * via {@link ResourceLeakDetector}. This method is a shortcut to {@link #touch(Object) touch(null)}. 调试时,记录当前对象访问的位置。如果对象确定内存泄漏,可以通过ResourceLeakDetector获取操作的相关信息。 此方法为 #touch(Object) touch(null)的快捷方式 */ ReferenceCounted touch(); /** * Records the current access location of this object with an additional arbitrary information for debugging * purposes. If this object is determined to be leaked, the information recorded by this operation will be * provided to you via {@link ResourceLeakDetector}. 调试时,记录当前对象访问的位置。如果对象确定内存泄漏,可以通过ResourceLeakDetector获取操作的相关信息。 */ ReferenceCounted touch(Object hint); /** * Decreases the reference count by {@code 1} and deallocates this object if the reference count reaches at * {@code 0}. *自减对象引用计数器,如果引用数为0,则回收对象。当且仅当对象引用计数器为0,回收对象,返回true * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated */ boolean release(); /** * Decreases the reference count by the specified {@code decrement} and deallocates this object if the reference * count reaches at {@code 0}. *减对象引用计数器,减量为decrement,如果引用数为0,则回收对象。当且仅当对象引用计数器为0,回收对象,返回true * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated */ boolean release(int decrement); }
从上面可以看出,对象引用计数器ReferenceCounted,主要记录对象的引用数量,当引用数量为0时,表示可以回收对象,在调试模式下,如果发现对象出现内存泄漏,可以用touch方法记录操作的相关信息,通过ResourceLeakDetector获取操作的相关信息,以便分析内存泄漏的原因。
再来看字节buf的接口定义:
package io.netty.buffer; import io.netty.util.ByteProcessor; import io.netty.util.ReferenceCounted; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.nio.channels.GatheringByteChannel; import java.nio.channels.ScatteringByteChannel; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; /** * A random and sequential accessible sequence of zero or more bytes (octets). * This interface provides an abstract view for one or more primitive byte * arrays ({@code byte[]}) and {@linkplain ByteBuffer NIO buffers}. *字节缓冲ByteBuf是一个可随机方法字节序列,字节数可以为0或更多。 这个方法提供了一个或更多原始字节数组和java nio ByteBuffer的抽象视图。 * <h3>Creation of a buffer</h3> *创建buf * It is recommended to create a new buffer using the helper methods in * {@link Unpooled} rather than calling an individual implementation's * constructor. *强烈建议使用Unpooled的辅助方法创建一个字节buf,而不是调用buf具体实现的构造方法。 * <h3>Random Access Indexing</h3> *随机访问索引 * Just like an ordinary primitive byte array, {@link ByteBuf} uses * [url=http://en.wikipedia.org/wiki/Zero-based_numbering]zero-based indexing[/url]. * It means the index of the first byte is always {@code 0} and the index of the last byte is * always {@link #capacity() capacity - 1}. For example, to iterate all bytes of a buffer, you * can do the following, regardless of its internal implementation: *如一般的字节数组一样,字节buf索引也是从0开始。意味着第一个字节的索引总是为0,最后一个字节的 索引总是为#capacity() capacity - 1。比如,遍历buf中的所有字节,忽略具体实现的情况下, 可以按如下code * <pre> * {@link ByteBuf} buffer = ...; * for (int i = 0; i < buffer.capacity(); i ++) { * byte b = buffer.getByte(i); * System.out.println((char) b); * } * </pre> * * <h3>Sequential Access Indexing</h3> *顺序访问索引 * {@link ByteBuf} provides two pointer variables to support sequential * read and write operations - {@link #readerIndex() readerIndex} for a read * operation and {@link #writerIndex() writerIndex} for a write operation * respectively. The following diagram shows how a buffer is segmented into * three areas by the two pointers: *字节buf提供了两个索引支持顺序读写操作,#readerIndex返回读操作使用的读索引readerIndex, #writerIndex返回写操作使用的写索引writerIndex。下图展示读写索引如何将buf分为三段。 * <pre> * +-------------------+------------------+------------------+ * | discardable bytes | readable bytes | writable bytes | * | | (CONTENT) | | * +-------------------+------------------+------------------+ * | | | | * 0 <= readerIndex <= writerIndex <= capacity * </pre> * * <h4>Readable bytes (the actual content)</h4> *可读字节(实际内容) * This segment is where the actual data is stored. Any operation whose name * starts with {@code read} or {@code skip} will get or skip the data at the * current {@link #readerIndex() readerIndex} and increase it by the number of * read bytes. If the argument of the read operation is also a * {@link ByteBuf} and no destination index is specified, the specified * buffer's {@link #writerIndex() writerIndex} is increased together. 这段内容为实际存储的数据。任何以read和skip开头的操作方法,将会从当前的读索引开始, 并增加读索引,增量为读取的字节数。如果读操作的参数为字节buf,并且没有目的索引, 那么目的buf写索引也会增加。 * <p> * If there's not enough content left, {@link IndexOutOfBoundsException} is * raised. The default value of newly allocated, wrapped or copied buffer's * {@link #readerIndex() readerIndex} is {@code 0}. *如果没有足够的内容,将会抛出IndexOutOfBoundsException异常。默认新分配, copy,包装的字节buf的读索引为0。 * <pre> * // Iterates the readable bytes of a buffer. * {@link ByteBuf} buffer = ...; * while (buffer.isReadable()) { * System.out.println(buffer.readByte()); * } * </pre> * * <h4>Writable bytes</h4> *可写字节 * This segment is a undefined space which needs to be filled. Any operation * whose name starts with {@code write} will write the data at the current * {@link #writerIndex() writerIndex} and increase it by the number of written * bytes. If the argument of the write operation is also a {@link ByteBuf}, * and no source index is specified, the specified buffer's * {@link #readerIndex() readerIndex} is increased together. 此段是需要填充的无定义空间。任何以write开头的操作方法,将会从当前的写索引开始写字节数据, 并增加写索引,增量为写的字节数。如果写操作的参数为字节buf,并且没有源索引,则源buf的读索引 将会增加 * <p> * If there's not enough writable bytes left, {@link IndexOutOfBoundsException} * is raised. The default value of newly allocated buffer's * {@link #writerIndex() writerIndex} is {@code 0}. The default value of * wrapped or copied buffer's {@link #writerIndex() writerIndex} is the * {@link #capacity() capacity} of the buffer. * 如果没有足够的可写字节,将抛出IndexOutOfBoundsException异常。默认新分配的buf的写索引为0。 copy,包装的字节buf的写索引为#capacity() capacity * <pre> * // Fills the writable bytes of a buffer with random integers. 写随机整数到buf * {@link ByteBuf} buffer = ...; * while (buffer.maxWritableBytes() >= 4) { * buffer.writeInt(random.nextInt()); * } * </pre> * * <h4>Discardable bytes</h4> *可丢弃的字节数 * This segment contains the bytes which were read already by a read operation. * Initially, the size of this segment is {@code 0}, but its size increases up * to the {@link #writerIndex() writerIndex} as read operations are executed. * The read bytes can be discarded by calling {@link #discardReadBytes()} to * reclaim unused area as depicted by the following diagram: *这段包含了读操作已经读取的字节。初始情况下,这段长度为0,但是这段的长度随着 读操作的执行,增加至写索引。这段数据可以调用#discardReadBytes方法丢弃, 并重新收回没用的区域,具体描述如下图: * <pre> * BEFORE discardReadBytes() * * +-------------------+------------------+------------------+ * | discardable bytes | readable bytes | writable bytes | * +-------------------+------------------+------------------+ * | | | | * 0 <= readerIndex <= writerIndex <= capacity * * * AFTER discardReadBytes() * * +------------------+--------------------------------------+ * | readable bytes | writable bytes (got more space) | * +------------------+--------------------------------------+ * | | | * readerIndex (0) <= writerIndex (decreased) <= capacity * </pre> * * Please note that there is no guarantee about the content of writable bytes * after calling {@link #discardReadBytes()}. The writable bytes will not be * moved in most cases and could even be filled with completely different data * depending on the underlying buffer implementation. *需要注意的是,在丢弃已经读取的字节时,并不能保证可写字节的内容。可写字节在大多数情况下不会 移动,甚至可能填充不同的数据,这个依赖于具体的buf实现。 * <h4>Clearing the buffer indexes</h4> *清除buf索引 * You can set both {@link #readerIndex() readerIndex} and * {@link #writerIndex() writerIndex} to {@code 0} by calling {@link #clear()}. * It does not clear the buffer content (e.g. filling with {@code 0}) but just * clears the two pointers. Please also note that the semantic of this * operation is different from {@link ByteBuffer#clear()}. *我们可以调用#clear方法,设置读写索引为0。clear方法不会清除buf中的数据,仅仅调整 读写索引。需要注意的是此方法不同于java nio ByteBuffer#clear方法。 * <pre> * BEFORE clear() * * +-------------------+------------------+------------------+ * | discardable bytes | readable bytes | writable bytes | * +-------------------+------------------+------------------+ * | | | | * 0 <= readerIndex <= writerIndex <= capacity * * * AFTER clear() * * +---------------------------------------------------------+ * | writable bytes (got more space) | * +---------------------------------------------------------+ * | | * 0 = readerIndex = writerIndex <= capacity * </pre> * * <h3>Search operations</h3> *搜索操作 * For simple single-byte searches, use {@link #indexOf(int, int, byte)} and {@link #bytesBefore(int, int, byte)}. * {@link #bytesBefore(byte)} is especially useful when you deal with a {@code NUL}-terminated string. * For complicated searches, use {@link #forEachByte(int, int, ByteProcessor)} with a {@link ByteProcessor} * implementation. 对于简单的单个字节搜索,可是使用#indexOf和#bytesBefore方法。当需要处理一个空字节NUL(0x00)时, #bytesBefore方法特别有用。 比如一些复杂的搜索,可以使用字节处理器ByteProcessor版的#forEachByte方法。 * * <h3>Mark and reset</h3> *标记和重置 * There are two marker indexes in every buffer. One is for storing * {@link #readerIndex() readerIndex} and the other is for storing * {@link #writerIndex() writerIndex}. You can always reposition one of the * two indexes by calling a reset method. It works in a similar fashion to * the mark and reset methods in {@link InputStream} except that there's no * {@code readlimit}. *在每个buf中有两个标记索引,一个是存储读索引的,一个是存储写索引的。你可以 调用reset方法,重置读、写索引到标记的位置。除了没有readlimit之外,与输入流中标记和重置方法 相似。 * <h3>Derived buffers</h3> *衍生buf * You can create a view of an existing buffer by calling one of the following methods: 你可通过如下方法,创建buf的视图: * [list] * [*]{@link #duplicate()} * [*]{@link #slice()} * [*]{@link #slice(int, int)} * [*]{@link #readSlice(int)} * [*]{@link #retainedDuplicate()} * [*]{@link #retainedSlice()} * [*]{@link #retainedSlice(int, int)} * [*]{@link #readRetainedSlice(int)} * [/list] * A derived buffer will have an independent {@link #readerIndex() readerIndex}, * {@link #writerIndex() writerIndex} and marker indexes, while it shares * other internal data representation, just like a NIO buffer does. 衍生buf,拥有自己独立的读写索引的标记索引,共享其他内部数据,就像java nio ByteBuffer * <p> * In case a completely fresh copy of an existing buffer is required, please * call {@link #copy()} method instead. *假如需要当前buf的完全拷贝,可以使用copy方法。 * <h4>Non-retained and retained derived buffers</h4> *非retained和retained衍生buf * Note that the {@link #duplicate()}, {@link #slice()}, {@link #slice(int, int)} and {@link #readSlice(int)} does NOT * call {@link #retain()} on the returned derived buffer, and thus its reference count will NOT be increased. If you * need to create a derived buffer with increased reference count, consider using {@link #retainedDuplicate()}, * {@link #retainedSlice()}, {@link #retainedSlice(int, int)} and {@link #readRetainedSlice(int)} which may return * a buffer implementation that produces less garbage. *注意#duplicate,#slice,#slice,#readSlice方法不会在衍生buf中调用#retain方法,这样buf的引用计数器将不会增加。 如果需要创建衍生buf,需要增加引用计数器,可以考虑上述方法的#retained*版本方法,这样可能会产生一点内存垃圾。 * <h3>Conversion to existing JDK types</h3> *转换ByteBuf为JDK 类型 * <h4>Byte array</h4> *字节数组 * If a {@link ByteBuf} is backed by a byte array (i.e. {@code byte[]}), * you can access it directly via the {@link #array()} method. To determine * if a buffer is backed by a byte array, {@link #hasArray()} should be used. *如果字节是一个字节数组,你可以直接使用#array访问。判断一个方法是否为字节数组,可以 使用#hasArray方法 * <h4>NIO Buffers</h4> *nio ByteBuffer * If a {@link ByteBuf} can be converted into an NIO {@link ByteBuffer} which shares its * content (i.e. view buffer), you can get it via the {@link #nioBuffer()} method. To determine * if a buffer can be converted into an NIO buffer, use {@link #nioBufferCount()}. *如果字节buf可以转换为java nio ByteBuffer,你可以调用#nioBuffer方法共享buf内容。 你可以使用#nioBufferCount来判断字节buf可不可以转换为java nio ByteBuffer * <h4>Strings</h4> *字符串 * Various {@link #toString(Charset)} methods convert a {@link ByteBuf} * into a {@link String}. Please note that {@link #toString()} is not a * conversion method. *#toString(Charset)方法转换字节buf为字符串,注意#toString不是一个转换方法 * <h4>I/O Streams</h4> *IO流 * Please refer to {@link ByteBufInputStream} and * {@link ByteBufOutputStream}. 参考ByteBufInputStream和ByteBufOutputStream */ @SuppressWarnings("ClassMayBeInterface") public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> { /** * Returns the number of bytes (octets) this buffer can contain. 获取buf容量 */ public abstract int capacity(); /** * Adjusts the capacity of this buffer. If the {@code newCapacity} is less than the current * capacity, the content of this buffer is truncated. If the {@code newCapacity} is greater * than the current capacity, the buffer is appended with unspecified data whose length is * {@code (newCapacity - currentCapacity)}. 调整buf的容量,如果容量小于原始buf容量,则truncated buf的内容,如果新增量大于原始容量, 则buffer将会添加不确定的数,其长度为newCapacity - currentCapacity */ public abstract ByteBuf capacity(int newCapacity); /** * Returns the maximum allowed capacity of this buffer. If a user attempts to increase the * capacity of this buffer beyond the maximum capacity using {@link #capacity(int)} or * {@link #ensureWritable(int)}, those methods will raise an * {@link IllegalArgumentException}. 返回buf的最大允许容量。如果用户尝试用 #capacity(int)和 #ensureWritable(int)方法, 增加buf容量超过最大容量,将会抛出非法参数异常 */ public abstract int maxCapacity(); /** * Returns the {@link ByteBufAllocator} which created this buffer. 返回创建buf的字节buf分配器 */ public abstract ByteBufAllocator alloc(); /** * Returns the [url=http://en.wikipedia.org/wiki/Endianness]endianness[/url] * of this buffer. *已丢弃 * @deprecated use the Little Endian accessors, e.g. {@code getShortLE}, {@code getIntLE} * instead of creating a buffer with swapped {@code endianness}. */ @Deprecated public abstract ByteOrder order(); /** * Returns a buffer with the specified {@code endianness} which shares the whole region, * indexes, and marks of this buffer. Modifying the content, the indexes, or the marks of the * returned buffer or this buffer affects each other's content, indexes, and marks. If the * specified {@code endianness} is identical to this buffer's byte order, this method can * return {@code this}. This method does not modify {@code readerIndex} or {@code writerIndex} * of this buffer. *已丢弃 * @deprecated use the Little Endian accessors, e.g. {@code getShortLE}, {@code getIntLE} * instead of creating a buffer with swapped {@code endianness}. */ @Deprecated public abstract ByteBuf order(ByteOrder endianness); /** * Return the underlying buffer instance if this buffer is a wrapper of another buffer. *如果buf为另一个buf包装类,返回底层buf实例,即返回未包装的buf * @return {@code null} if this buffer is not a wrapper */ public abstract ByteBuf unwrap(); /** * Returns {@code true} if and only if this buffer is backed by an * NIO direct buffer. 判断buf是否是direct类型 */ public abstract boolean isDirect(); /** * Returns {@code true} if and only if this buffer is read-only. 判断buf是否可读 */ public abstract boolean isReadOnly(); /** * Returns a read-only version of this buffer. 返回buf的只读版本 */ public abstract ByteBuf asReadOnly(); /** * Returns the {@code readerIndex} of this buffer. 获取buf的读索引 */ public abstract int readerIndex(); /** * Sets the {@code readerIndex} of this buffer. *设置buf的读索引 * @throws IndexOutOfBoundsException * if the specified {@code readerIndex} is * less than {@code 0} or * greater than {@code this.writerIndex} */ public abstract ByteBuf readerIndex(int readerIndex); /** * Returns the {@code writerIndex} of this buffer. 获取buf的写索引 */ public abstract int writerIndex(); /** * Sets the {@code writerIndex} of this buffer. *设置buf的写索引 * @throws IndexOutOfBoundsException * if the specified {@code writerIndex} is * less than {@code this.readerIndex} or * greater than {@code this.capacity} */ public abstract ByteBuf writerIndex(int writerIndex); /** * Sets the {@code readerIndex} and {@code writerIndex} of this buffer * in one shot. This method is useful when you have to worry about the * invocation order of {@link #readerIndex(int)} and {@link #writerIndex(int)} * methods. For example, the following code will fail: *设置buf读写索引的快捷方式。当你不得不关心读索引设置和写索引设置的顺序时,这个方法,非常有用。 以下代码将会失败: * <pre> * // Create a buffer whose readerIndex, writerIndex and capacity are * // 0, 0 and 8 respectively. * {@link ByteBuf} buf = {@link Unpooled}.buffer(8); * * // IndexOutOfBoundsException is thrown because the specified * // readerIndex (2) cannot be greater than the current writerIndex (0). 读索引不能大于当前的写索引 * buf.readerIndex(2); * buf.writerIndex(4); * </pre> * * The following code will also fail: *同样下面的代码会失败 * <pre> * // Create a buffer whose readerIndex, writerIndex and capacity are * // 0, 8 and 8 respectively. * {@link ByteBuf} buf = {@link Unpooled}.wrappedBuffer(new byte[8]); * * // readerIndex becomes 8. * buf.readLong(); * * // IndexOutOfBoundsException is thrown because the specified * // writerIndex (4) cannot be less than the current readerIndex (8). 写索引小于读索引 * buf.writerIndex(4); * buf.readerIndex(2); * </pre> * * By contrast, this method guarantees that it never * throws an {@link IndexOutOfBoundsException} as long as the specified * indexes meet basic constraints, regardless what the current index * values of the buffer are: *相比之下,setIndex方法可以保证只要索引满足基本的约束,无论当前buf索引的值是什么, 索引越界异常不会抛出. * <pre> * // No matter what the current state of the buffer is, the following * // call always succeeds as long as the capacity of the buffer is not * // less than 4. 只要buf的容量大于4,就不会抛出异常 * buf.setIndex(2, 4); * </pre> * * @throws IndexOutOfBoundsException * if the specified {@code readerIndex} is less than 0, * if the specified {@code writerIndex} is less than the specified * {@code readerIndex} or if the specified {@code writerIndex} is * greater than {@code this.capacity} */ public abstract ByteBuf setIndex(int readerIndex, int writerIndex); /** * Returns the number of readable bytes which is equal to 获取buf可读字节数为writerIndex - readerIndex * {@code (this.writerIndex - this.readerIndex)}. */ public abstract int readableBytes(); /** * Returns the number of writable bytes which is equal to 获取buf可写字节数为capacity - writerIndex * {@code (this.capacity - this.writerIndex)}. */ public abstract int writableBytes(); /** * Returns the maximum possible number of writable bytes, which is equal to * {@code (this.maxCapacity - this.writerIndex)}. 当前buf可写的最大字节数为maxCapacity - writerIndex */ public abstract int maxWritableBytes(); /** * Returns {@code true} * if and only if {@code (this.writerIndex - this.readerIndex)} is greater * than {@code 0}. 获取buf是否可读,如果当前可读字节数大于0,表示可读,返回true */ public abstract boolean isReadable(); /** * Returns {@code true} if and only if this buffer contains equal to or more than the specified number of elements. buf的可读字节数据是否大于size */ public abstract boolean isReadable(int size); /** * Returns {@code true} * if and only if {@code (this.capacity - this.writerIndex)} is greater * than {@code 0}. buf是否可写,即this.capacity - this.writerIndex是否大于0 */ public abstract boolean isWritable(); /** * Returns {@code true} if and only if this buffer has enough room to allow writing the specified number of * elements. 判断当前buf是否可容下size字节 */ public abstract boolean isWritable(int size); /** * Sets the {@code readerIndex} and {@code writerIndex} of this buffer to * {@code 0}. 重置buf的读写索引为0,等同于setIndex(0, 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. 主要此方法,不同于Java nio buffer,设置buf的limit的位置为capacity */ 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}. 标记当前buf的读索引。我们可以调用#resetReaderIndex方法,重回标记的读索引位置。 初始标记位置为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}. 标记当前buf的写索引。我们可以调用#resetWriterIndex方法,重回标记的写索引位置。 初始标记位置为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. 丢弃0索引到当前读索引的数据。并移到读索引到写索引之间的数据,到0索引位置上, 重置读索引为0,写索引为oldWriterIndex - oldReaderIndex * <p> * Please refer to the class documentation for more detailed explanation. 更详细的扩展,请参考具体的class文档 */ 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. 与ByteBuf#discardReadBytes方法相似,此方可能会在内存出现负载时,丢弃一些或所有, 或不丢弃可读字节数据,具体依赖具体的实现,以减少内存的使用量。 */ public abstract ByteBuf discardSomeReadBytes(); /** * Makes sure the number of {@linkplain #writableBytes() the writable bytes} * is equal to or greater than the specified value. If there is enough * writable bytes in this buffer, this method returns with no side effect. * Otherwise, it raises an {@link IllegalArgumentException}. 确保当前buf可以容下minWritableBytes个字节数据,如果buf足够写,则方法返回没有任何影响, 否则抛出非法参数异常 * * @param minWritableBytes * the expected minimum number of writable bytes * @throws IndexOutOfBoundsException * if {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()} */ public abstract ByteBuf ensureWritable(int minWritableBytes); /** * Tries to make sure the number of {@linkplain #writableBytes() the writable bytes} * is equal to or greater than the specified value. Unlike {@link #ensureWritable(int)}, * this method does not raise an exception but returns a code. *尝试确保buf可以写minWritableBytes字节数据。与#ensureWritable(int)方法不同的时,不会抛出异常 * @param minWritableBytes * the expected minimum number of writable bytes * @param force * When {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()}: * [list] * [*]{@code true} - the capacity of the buffer is expanded to {@link #maxCapacity()} * [*]{@code false} - the capacity of the buffer is unchanged 当force为true,空间不足时,扩展buf容量为最大容量; false表示,空间不足时,容量没有任何改变 * [/list] * @return {@code 0} if the buffer has enough writable bytes, and its capacity is unchanged. * {@code 1} if the buffer does not have enough bytes, and its capacity is unchanged. * {@code 2} if the buffer has enough writable bytes, and its capacity has been increased. * {@code 3} if the buffer does not have enough bytes, but its capacity has been * increased to its maximum. 返回代码0,表示buf可以容下minWritableBytes个字节数据; 1表示,没有足够的空间可写,容量没有变化; 2表示,buf可以容下minWritableBytes个字节数据,容量扩展; 3表示,buf空间不够,容量扩展至最大值。 */ public abstract int ensureWritable(int minWritableBytes, boolean force); /** * 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); /** * 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}). *从当前buf的index绝对索引开始,转移当前buf的数据到dst buf中。此方法与#getBytes(int, ByteBuf, int, int)方法相似, 不同的时,此方法将会改变dst buf的写索引,而#getBytes(int, ByteBuf, int, int)不会。此方法不会改变当前buf的 读写索引。 * @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}). *与上面方法不同的是,转移的数据的长度为length * @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. *从当前buf的绝对索引index开始,转移length长度的数据到dst buf中,dstIndex绝对索引开始, 此方法不会修改源buf和目的buf的读写索引位置。 * @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 *从当前buf的绝对index开始,转移数据到,目的dst 字节数据中,此方法不会修改当前buf的读写索引。 * @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. *与上面方法是,转移的字节长度为length,从目的字节数组的dstIndex索引开始 * @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. *从当前buf的绝对索引index开始,转移数据到目的nio buf中,直至到达目的nio buf的limit的位置 ,此方法不会修改当前buf的读写索引,会修改nio buf的位置索引position * @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. *从当前buf的绝对索引index开始,转移数据到目的OutputStream中,直至到达目的nio buf的limit的位置 ,此方法不会修改当前buf的读写索引 * @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. *从当前buf的绝对索引index开始,转移数据到目的聚集字节通道GatheringByteChannel中, ,此方法不会修改当前buf的读写索引 * @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; /** * Transfers this buffer's data starting at the specified absolute {@code index} * to the specified channel starting at the given file position. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. This method does not modify the channel's position. *从当前buf的绝对索引index开始,转移数据到目的文件域FileChannel中, 此方法不会修改当前buf的读写索引,同时不会修改文件域的位置索引position * @param position the file position at which the transfer is to begin * @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, FileChannel out, long position, int length) throws IOException; /** * Gets a {@link CharSequence} with the given length at the given index. *从buf的index索引开始,获取给定长度字符序列 * @param length the length to read * @param charset that should be used * @return the sequence * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract CharSequence getCharSequence(int index, int length, Charset charset); /** * 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. *从buf的索引index开始,设置特殊的字节,一些特殊值的高24位将会被忽略,不会修改buf的读写索引 * @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); /** * 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}). *从源buf转移数据到当前buf的绝对索引index上,直到源buf不可读。此方法与setBytes(int, ByteBuf, int, int) 相同,不同的时此方法会增加源buf的索引,而setBytes(int, ByteBuf, int, int)不会。 此方法不为修改源buf的读写索引 * @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}). *与上面不同的时,从源buf转移指定长度的数据 * @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. *与上面个方法不同的是,此方法是从源buf的srcIndex索引开始读数据,并且不会修改源buf和 目的buf的索引。 * @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. *转移源字节数组中的数据到当前buf的index位置,不会修改当前buf的索引。 * @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. *与上面不同的是此方法是从源buf的srcIndex索引开始读数据,并且字节长度为length * @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. *转移nio ByteBuffer中的数据到当前buf,直到位置索引到达limit位置,此方法不会修改读写索引 * @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. *转移目的输入流的数据到当前buf,,此方法不会修改读写索引 * @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. *转移目的分散字节通道的数据到当前buf,,此方法不会修改读写索引 * @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; /** * Transfers the content of the specified source channel starting at the given file position * to this buffer starting at the specified absolute {@code index}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. This method does not modify the channel's position. *转移目的文件通道的数据到当前buf,,此方法不会修改读写索引 * @param position the file position at which the transfer is to begin * @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, FileChannel in, long position, 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. *从buf的index位置,填充字节buf为NUL (0x00),此方法不会修改当前buf中的索引位置 * @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); /** * Writes the specified {@link CharSequence} at the current {@code writerIndex} and increases * the {@code writerIndex} by the written bytes. *从当前写索引位置开始,写字符序列到当前buf,并更新写索引 * @param index on which the sequence should be written * @param sequence to write * @param charset that should be used. * @return the written number of bytes. * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is not large enough to write the whole sequence */ public abstract int setCharSequence(int index, CharSequence sequence, Charset charset); /** * Gets a byte at the current {@code readerIndex} and increases * the {@code readerIndex} by {@code 1} in this buffer. * 从buf当前的读索引开始,读取一个字节数据,读索引向前移一位 * @throws IndexOutOfBoundsException * if {@code this.readableBytes} is less than {@code 1} */ public abstract byte readByte(); /** * 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. *从当前buf的读索引开始转移length字节数据到新创建的buf中,并增加当前buf的读索引, 新创建的buf的读索引为0,写索引为length * @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}). 返回当前buf的读索引开始,长度为length的字节切片 * <p> * Also be aware that this method will NOT call {@link #retain()} and so the * reference count will NOT be increased. * 注意此方法不会调用retain方法,索引buf的引用计数器不会变 * @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); /** * Returns a new retained 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}). * <p> * Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #readSlice(int)}. * This method behaves similarly to {@code readSlice(...).retain()} except that this method may return * a buffer implementation that produces less garbage. *与上面方法不同的时,会增加buf的引用计数器,会产生少量的垃圾 * @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 readRetainedSlice(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. *从当前buf的读索引开始,转移数据到目的buf,直到当前buf不可读,同时更新当前buf的读索引。 此方法,与#readBytes(ByteBuf, int, int)基本相同,不同的是此方法会增加目的字节buf的写索引, 而#readBytes(ByteBuf, int, int)不会。 * @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. *与上面方法不同到的是,从当前buf读取指定长度的字节数据 * @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}). *此方法,与上面方法不同的是,将当前buf的数据放到目的buf的dstIndex位置,同时, 此方法不会修改目的buf的写索引 * @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}). *从当前buf的读索引开始,转移数据到目的字节数组中 * @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}). *与上面方法不同的是,转移字节长度为length,并方法目的字节数组的dstIndex上 * @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. *从当前buf的读索引开始,转移数据到java nio ByteBuffer中,同时会更新当前buf的读索引 * @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}. *从当前buf的读索引开始,转移数据到输出流OutputStream中 * @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}. *从当前buf的读索引开始,转移数据到目的聚集通道中 * @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; /** * Gets a {@link CharSequence} with the given length at the current {@code readerIndex} * and increases the {@code readerIndex} by the given length. *从当前buf的读索引开始,转移length长度的字节数据到目的字符序列中,同时会更新当前buf的读索引 * @param length the length to read * @param charset that should be used * @return the sequence * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract CharSequence readCharSequence(int length, Charset charset); /** * Transfers this buffer's data starting at the current {@code readerIndex} * to the specified channel starting at the given file position. * This method does not modify the channel's position. *从当前buf的读索引开始,转移数据到目的文件通道中,不会修改文件通道的位置 * @param position the file position at which the transfer is to begin * @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(FileChannel out, long position, int length) throws IOException; /** * Increases the current {@code readerIndex} by the specified * {@code length} in this buffer. *增加读索引位置length长度,向前移动length位置 * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract ByteBuf skipBytes(int length); /** * Sets the specified boolean at the current {@code writerIndex} * and increases the {@code writerIndex} by {@code 1} in this buffer. * 从buf当前写索引位置写一个布尔值,写索引向前移一位 * @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. * 从buf当前写索引位置写一个字节,写索引向前移一位。 一些特殊值的高24位将会被忽略 * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is less than {@code 1} */ public abstract ByteBuf writeByte(int 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. *从当前buf写索引开始,转移源buf中的数据到当前buf的中,直到源buf不可读,同时更新当前buf的写索引, 此方法与#writeBytes(ByteBuf, int, int)基本相同,除了此方法回修改源buf的读索引,而#writeBytes(ByteBuf, int, int) 不会。 * @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. * 与上面方法不同的时,限制源buf转移数据的长度 * @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}). * 与上面方法不同的是,转移数据从指定索引开始srcIndex * @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}). * 写字节数组中的数据到当前buf,并更新当前buf的写索引 * @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. 写java nio ByteBuffer中的数据到当前buf,直到ByteBuffer的位置索引到limit位置,同时更新写索引 * * @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. *写输入流InputStream中的length个字节数据到当前buf,同时更新写索引 * @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. *写分散字节通道ScatteringByteChannel中的length个字节数据到当前buf,同时更新写索引 * @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; /** * Transfers the content of the specified channel starting at the given file position * to this buffer starting at the current {@code writerIndex} and increases the * {@code writerIndex} by the number of the transferred bytes. * This method does not modify the channel's position. *写文件FileChannel中的length个字节数据到当前buf,同时更新写索引,不会修改通道的位置索引 * @param position the file position at which the transfer is to begin * @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(FileChannel in, long position, 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}. *从当前写索引开始,填充length个NUL (0x00) * @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); /** * Writes the specified {@link CharSequence} at the current {@code writerIndex} and increases * the {@code writerIndex} by the written bytes. * in this buffer. *从当前写索引,写字符序列到当前buf * @param sequence to write * @param charset that should be used * @return the written number of bytes * @throws IndexOutOfBoundsException * if {@code this.writableBytes} is not large enough to write the whole sequence */ public abstract int writeCharSequence(CharSequence sequence, Charset charset); /** * 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. 返回当前buf 可读字节的拷贝。修改返回的copy buf,不会影响当前buf。此方法与 buf.copy(buf.readerIndex(), buf.readableBytes())方法相同,不会修改读写索引 */ 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. 返回当前buf的可读字节数据的切片slice,当他们维护各自的索引和标记时, 修改返回的切片buf或当前buf,会相互影响buf数据,此方法等同于 buf.slice(buf.readerIndex(), buf.readableBytes()),此方法不会修改读写索引 * <p> * Also be aware that this method will NOT call {@link #retain()} and so the * reference count will NOT be increased. 注意,此方法不会调用retain方法,即不会增加buf的引用计数器 */ 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. 此方法与上面方法,不同的是,限定了切片数据开始索引和字节的长度 * <p> * Also be aware that this method will NOT call {@link #retain()} and so the * reference count will NOT be increased. */ public abstract ByteBuf slice(int index, int length); /** * Returns a retained 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. * <p> * Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice()}. * This method behaves similarly to {@code slice().retain()} except that this method may return * a buffer implementation that produces less garbage. 与#slice方法不同的是,会调用retain方法,即增加buf的引用计数器,同时可能会产生一些内存垃圾 */ public abstract ByteBuf retainedSlice(); /** * Returns a retained 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. * <p> * Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice(int, int)}. * This method behaves similarly to {@code slice(...).retain()} except that this method may return * a buffer implementation that produces less garbage. 此方法与上面方法,不同的是,限定了切片数据开始索引和字节的长度 */ public abstract ByteBuf retainedSlice(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 does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. 返回buf的整个共享域,当他们维护各自的索引和标记时, 修改返回的buf或当前buf,会相互影响buf数据,此方法不会修改读写索引 * <p> * The reader and writer marks will not be duplicated. Also be aware that this method will * NOT call {@link #retain()} and so the reference count will NOT be increased. * @return A buffer whose readable content is equivalent to the buffer returned by {@link #slice()}. * However this buffer will share the capacity of the underlying buffer, and therefore allows access to all of the * underlying content if necessary. 读写标记不会复制。同时此方法不会调用retain方法,即不会增加buf的引用计数器, 返回的buf的可读内容相当于#slice方法返回的buf。不同的是,此方法返回的buf与底层buf共享容量, 因此如果需要,运行方法底层的数据内容 */ public abstract ByteBuf duplicate(); /** * Returns a retained 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. * <p> * Note that this method returns a {@linkplain #retain() retained} buffer unlike {@link #slice(int, int)}. * This method behaves similarly to {@code duplicate().retain()} except that this method may return * a buffer implementation that produces less garbage. 与上述方法不同的是,会调用retain方法,即增加buf的引用计数器,同时可能会产生一些内存垃圾 */ public abstract ByteBuf retainedDuplicate(); /** * 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. *返回包含当前buf的最大java nio ByteBuffer数量。注意#nioBuffers和#nioBuffers(int, int)方法,可能 返回更少数量的ByteBuffer * @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. * 如果当前buf没有底层ByteBuffer,则返回-1。如果当前buf至少有一个ByteBuffer,则返回数量。注意为了避免 冲突,此方法不会返回0。 * @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. * 暴露当前buf的可读数据到一个java nio ByteBuffer中。返回的java nio ByteBuffer与当前buf共享数据, 但修改java nio ByteBuffer的位置和limit,不会修改当前buf的索引和标记。 此方法与buf.nioBuffer(buf.readerIndex(), buf.readableBytes()相同。此方法不会修改当前buf的读写索引。 如果当前buf是一个动态的buf,调整buf容量时,java nio ByteBuffer 是看不到容量的改变的。 * @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. *与上面不同的时,限定了共享region的开始索引和数据长度 * @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. 内部使用,暴露一个内部的nio buf */ 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. * *与#nioBuffer方法不同的是返回的是一个nio buf数组 * @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. *与上面不同的时,限定了共享region的开始索引和数据长度 * @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); /** * Returns {@code true} if and only if this buffer has a backing byte array. * If this method returns true, you can safely call {@link #array()} and * {@link #arrayOffset()}. 当前仅当,buf由于有一个backing 字节数组,返回true。如果方法返回true,则可以调用 #array() 和 #arrayOffset()方法. */ public abstract boolean hasArray(); /** * Returns the backing byte array of this buffer. *返回当前buf的backing字节数组 * @throws UnsupportedOperationException * if there no accessible backing byte array */ public abstract byte[] array(); /** * Returns the offset of the first byte within the backing byte array of * this buffer. *返回当前buf backing数组第一个字节在buf中的位置 * @throws UnsupportedOperationException * if there no accessible backing byte array */ public abstract int arrayOffset(); /** * Returns {@code true} if and only if this buffer has a reference to the low-level memory address that points * to the backing data. 当且仅当,当前buf有一个指向backing数据的低位内存地址引用时,返回true */ public abstract boolean hasMemoryAddress(); /** * Returns the low-level memory address that point to the first byte of ths backing data. * 返回buf中第一个字节的低位内存地址 * @throws UnsupportedOperationException * if this buffer does not support accessing the low-level memory address */ public abstract long memoryAddress(); /** * Decodes this buffer's readable bytes into a string with the specified * character set name. This method is identical to * {@code buf.toString(buf.readerIndex(), buf.readableBytes(), charsetName)}. * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *解码可读字节数据为,更定字符编码的字符串,此方法相当与 buf.toString(buf.readerIndex(), buf.readableBytes(), charsetName), 此方法不会修改读写索引。 * @throws UnsupportedCharsetException * if the specified character set name is not supported by the * current VM */ public abstract String toString(Charset charset); /** * Decodes this buffer's sub-region into a string with the specified * character set. This method does not modify {@code readerIndex} or * {@code writerIndex} of this buffer. 此方法与上面方法,不同的是,限定了buf数据开始索引和字节的长度 */ public abstract String toString(int index, int length, Charset charset); /** * Returns a hash code which was calculated from the content of this * buffer. If there's a byte array which is * {@linkplain #equals(Object) equal to} this array, both arrays should * return the same value. 返回buf内容的hash code。如果buf的字节数组相等,则返回相同hash code */ @Override public abstract int hashCode(); /** * Determines if the content of the specified buffer is identical to the * content of this array. 'Identical' here means: * [list] * [*]the size of the contents of the two buffers are same and * [*]every single byte of the content of the two buffers are same. * [/list] * Please note that it does not compare {@link #readerIndex()} nor * {@link #writerIndex()}. This method also returns {@code false} for * {@code null} and an object which is not an instance of * {@link ByteBuf} type. 判断对象是否想定,当且仅当两个buf中的所有的字节相等,则对象相等,不比较索引, 如果对象不是字节buf,则返回false */ @Override public abstract boolean equals(Object obj); /** * Compares the content of the specified buffer to the content of this * buffer. Comparison is performed in the same manner with the string * comparison functions of various languages such as {@code strcmp}, * {@code memcmp} and {@link String#compareTo(String)}. 比较buf,以字符串的比较形式 */ @Override public abstract int compareTo(ByteBuf buffer); /** * Returns the string representation of this buffer. This method does not * necessarily return the whole content of the buffer but returns * the values of the key properties such as {@link #readerIndex()}, * {@link #writerIndex()} and {@link #capacity()}. 返回buf所表示的字符串,从读索引到写索引位置 */ @Override public abstract String toString(); //增加字节buf引用计数器,增量为increment @Override public abstract ByteBuf retain(int increment); //自增字节buf引用计数器 @Override public abstract ByteBuf retain(); @Override public abstract ByteBuf touch(); //调试时,记录buf操作的相关信息,以便分析内存泄漏问题 @Override public abstract ByteBuf touch(Object hint); }
总结:
对象引用计数器ReferenceCounted,主要记录对象的引用数量,当引用数量为0时,表示可以回收对象,在调试模式下,如果发现对象出现内存泄漏,可以用touch方法记录操作的相关信息,通过ResourceLeakDetector获取操作的相关信息,以便分析内存泄漏的原因。
字节缓存ByteBuf继承了对象引用计数器ReferenceCounted,拥有一个最大容量限制,如果用户尝试用 #capacity(int)和 #ensureWritable(int)方法,增加buf容量超过最大容量,将会抛出非法参数异常;字节buf有两个索引,一个为读索引readerIndex,一个为写索引writerIndex,读索引不能大于写索引,写索引不能小于读索引,buf可读字节数为writerIndex - readerIndex,buf可写字节数为capacity - writerIndex,buf可写的最大字节数为maxCapacity - writerIndex;
可以使用markReader/WriterIndex标记当前buf读写索引位置,resetReader/WriterIndex方法可以重回先前标记的索引位置;
当内存空间负载过度时,我们可以使用discardReadBytes丢弃一些数据,以节省空间;
我们可以使用ensureWritable检测当buf是否有足够的空间写数据;
提供了getBytes方法,可以将buf中的数据转移到目的ByteBuf,Byte数组,Nio字节buf ByteBuffer,OutputStream,聚集字节通道
GatheringByteChannel和文件通道FileChannel中,这些方法不会修改当前buf读写索引,具体是否修改目的对象索引或位置,见java doc 描述。
提供了setBytes方法,可以将源ByteBuf,Byte数组,Nio字节buf ByteBuffer,InputputStream,分散字节通道ScatteringByteChannel和文件通道FileChannel中的数据转移到当前buf中,这些方法不会修改当前buf的读写索引,至于源对象索引或位置,见java doc 描述。
提供了readBytes方法,可以将buf中的数据转移到目的ByteBuf,Byte数组,Nio字节buf ByteBuffer,OutputStream,聚集字节通道GatheringByteChannel和文件通道FileChannel中,这些方法具体会会修改当前buf读索引,至于会不会修改源对象索引或位置,见java doc 描述。
提供了writeBytes方法,可以将源ByteBuf,Byte数组,Nio字节buf ByteBuffer,
InputputStream,分散字节通道ScatteringByteChannel和文件通道FileChannel中的数据写到当前buf中,这些方法会修改当前buf的写索引,至于会不会修改源对象索引或位置,见java
doc 描述。
set*原始类型方法不会修改读写索引;
get*原始类型方法不会修改读写索引;
write*原始类型方法会修改写索引;
read*原始类型方法,会修改读索引;
字节buf中的set/get*方法不会修改当前buf的读写索引,而write*修改写索引,read*会修改读索引;
提供了copy,slice和retainSlice,duplicate和retainedDuplicate方法,用于拷贝,切割,复制当前buf数据,retained*方法会增加buf的引用计数器;
提供nioBuffer和nioBuffers方法,用于包装当前buf可读数据为java nio ByteBuffer和ByteBuffer数组。
附:
下面是字节buf的get*原始类型方法的定义,简单看一下:
下面的方法不会修改读写索引
/** * 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 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 a 16-bit short integer at the specified absolute {@code index} in * this buffer in Little Endian Byte Order. 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 getShortLE(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 an unsigned 16-bit short integer at the specified absolute * {@code index} in this buffer in Little Endian Byte Order. * 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 getUnsignedShortLE(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 a 24-bit medium integer at the specified absolute {@code index} in * this buffer in the Little Endian Byte Order. 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 getMediumLE(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 an unsigned 24-bit medium integer at the specified absolute * {@code index} in this buffer in Little Endian Byte Order. * 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 getUnsignedMediumLE(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 a 32-bit integer at the specified absolute {@code index} in * this buffer with Little Endian Byte Order. 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 getIntLE(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 an unsigned 32-bit integer at the specified absolute {@code index} * in this buffer in Little Endian Byte Order. 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 getUnsignedIntLE(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 64-bit long integer at the specified absolute {@code index} in * this buffer in Little Endian Byte Order. 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 getLongLE(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);
下面一些set*原始类型方法从索引index开始,设置原始类型,不会修改读写索引
/** * 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 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 16-bit short integer at the specified absolute * {@code index} in this buffer with the Little Endian Byte Order. * 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 setShortLE(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 24-bit medium integer at the specified absolute * {@code index} in this buffer in the Little Endian Byte Order. * 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 setMediumLE(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 32-bit integer at the specified absolute * {@code index} in this buffer with Little Endian byte order * . * 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 setIntLE(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 64-bit long integer at the specified absolute * {@code index} in this buffer in Little Endian Byte Order. * 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 setLongLE(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);
以下一些read*原始类型方法,会修改读索引
/** * 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 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 a 16-bit short integer at the current {@code readerIndex} * in the Little Endian Byte Order 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 readShortLE(); /** * 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 an unsigned 16-bit short integer at the current {@code readerIndex} * in the Little Endian Byte Order 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 readUnsignedShortLE(); /** * 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 a 24-bit medium integer at the current {@code readerIndex} * in the Little Endian Byte Order 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 readMediumLE(); /** * 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 an unsigned 24-bit medium integer at the current {@code readerIndex} * in the Little Endian Byte Order 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 readUnsignedMediumLE(); /** * 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 a 32-bit integer at the current {@code readerIndex} * in the Little Endian Byte Order 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 readIntLE(); /** * 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 an unsigned 32-bit integer at the current {@code readerIndex} * in the Little Endian Byte Order 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 readUnsignedIntLE(); /** * 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 64-bit integer at the current {@code readerIndex} * in the Little Endian Byte Order 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 readLongLE(); /** * 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();
下面是一些write*原始类型的方法,会增加写索引
/** * 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 16-bit short integer in the Little Endian Byte * Order 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 writeShortLE(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 24-bit medium integer at the current * {@code writerIndex} in the Little Endian Byte Order 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 writeMediumLE(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 32-bit integer at the current {@code writerIndex} * in the Little Endian Byte Order 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 writeIntLE(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 64-bit long integer at the current * {@code writerIndex} in the Little Endian Byte Order 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 writeLongLE(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);
下面是一些字节搜索定位方法:
/** * Locates the first occurrence of the specified {@code value} in this * buffer. The search takes place from the specified {@code fromIndex} * (inclusive) to the specified {@code toIndex} (exclusive). 查找在当buf的fromIndex(inclusive)和toIndex(exclusive),之间是否存在指定的字节, 找到返回对应的索引,否则返回-1 * <p> * If {@code fromIndex} is greater than {@code toIndex}, the search is * performed in a reversed order. 如果fromIndex大于toIndex,则反向执行搜索 * <p> * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. 此方法不会修改读写索引 * * @return the absolute index of the first occurrence if found. * {@code -1} otherwise. */ public abstract int indexOf(int fromIndex, int toIndex, byte value); /** * Locates the first occurrence of the specified {@code value} in this * buffer. The search takes place from the current {@code readerIndex} * (inclusive) to the current {@code writerIndex} (exclusive). * <p> 从当前buf的读索引开始,到写索引之间,搜索是否存在指定字节,存在则返回第一次发生的索引, 否则返回-1 * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. 此方法不会修改读写索引 * * @return the number of bytes between the current {@code readerIndex} * and the first occurrence if found. {@code -1} otherwise. */ public abstract int bytesBefore(byte value); /** * Locates the first occurrence of the specified {@code value} in this * buffer. The search starts from the current {@code readerIndex} * (inclusive) and lasts for the specified {@code length}. 与上面方法不同的是,不是到写索引,而是指定了搜索返回即[readerIndex,readerIndex+length) * <p> * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *此方法不会修改读写索引 * @return the number of bytes between the current {@code readerIndex} * and the first occurrence if found. {@code -1} otherwise. * * @throws IndexOutOfBoundsException * if {@code length} is greater than {@code this.readableBytes} */ public abstract int bytesBefore(int length, byte value); /** * Locates the first occurrence of the specified {@code value} in this * buffer. The search starts from the specified {@code index} (inclusive) * and lasts for the specified {@code length}. 与上面方法不同的是,从指定的索引开始搜索 * <p> * This method does not modify {@code readerIndex} or {@code writerIndex} of * this buffer. *此方法不会修改读写索引 * @return the number of bytes between the specified {@code index} * and the first occurrence if found. {@code -1} otherwise. * * @throws IndexOutOfBoundsException * if {@code index + length} is greater than {@code this.capacity} */ public abstract int bytesBefore(int index, int length, byte value); 再来遍历buf,处理字节: /** * Iterates over the readable bytes of this buffer with the specified {@code processor} in ascending order. * 遍历buf,以升序ByteProcessor#process处理字节 * @return {@code -1} if the processor iterated to or beyond the end of the readable bytes. * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}. 如果迭代器超过可读索引位置,则返回-1,否则返回上次ByteProcessor#process(byte)方法,返回false的索引位置 */ public abstract int forEachByte(ByteProcessor processor); /** * Iterates over the specified area of this buffer with the specified {@code processor} in ascending order. * (i.e. {@code index}, {@code (index + 1)}, .. {@code (index + length - 1)}) *与上面的不同的多了开始索引,和范围控制length * @return {@code -1} if the processor iterated to or beyond the end of the specified area. * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}. */ public abstract int forEachByte(int index, int length, ByteProcessor processor); /** * Iterates over the readable bytes of this buffer with the specified {@code processor} in descending order. *降序方式ByteProcessor#process处理字节 * @return {@code -1} if the processor iterated to or beyond the beginning of the readable bytes. * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}. */ public abstract int forEachByteDesc(ByteProcessor processor); /** * Iterates over the specified area of this buffer with the specified {@code processor} in descending order. * (i.e. {@code (index + length - 1)}, {@code (index + length - 2)}, ... {@code index}) *与上面的不同的多了开始索引,和范围控制length * * @return {@code -1} if the processor iterated to or beyond the beginning of the specified area. * The last-visited index If the {@link ByteProcessor#process(byte)} returned {@code false}. */ public abstract int forEachByteDesc(int index, int length, ByteProcessor processor);
//ByteProcessor
package io.netty.util; /** * Provides a mechanism to iterate over a collection of bytes. */ public interface ByteProcessor { /** * A {@link ByteProcessor} which finds the first appearance of a specific byte. */ class IndexOfProcessor implements ByteProcessor { private final byte byteToFind; public IndexOfProcessor(byte byteToFind) { this.byteToFind = byteToFind; } @Override public boolean process(byte value) { return value != byteToFind; } } /** * A {@link ByteProcessor} which finds the first appearance which is not of a specific byte. */ class IndexNotOfProcessor implements ByteProcessor { private final byte byteToNotFind; public IndexNotOfProcessor(byte byteToNotFind) { this.byteToNotFind = byteToNotFind; } @Override public boolean process(byte value) { return value == byteToNotFind; } } /** * Aborts on a {@code NUL (0x00)}. */ ByteProcessor FIND_NUL = new IndexOfProcessor((byte) 0); /** * Aborts on a non-{@code NUL (0x00)}. */ ByteProcessor FIND_NON_NUL = new IndexNotOfProcessor((byte) 0); /** * Aborts on a {@code CR ('\r')}. */ ByteProcessor FIND_CR = new IndexOfProcessor((byte) '\r'); /** * Aborts on a non-{@code CR ('\r')}. */ ByteProcessor FIND_NON_CR = new IndexNotOfProcessor((byte) '\r'); /** * Aborts on a {@code LF ('\n')}. */ ByteProcessor FIND_LF = new IndexOfProcessor((byte) '\n'); /** * Aborts on a non-{@code LF ('\n')}. */ ByteProcessor FIND_NON_LF = new IndexNotOfProcessor((byte) '\n'); /** * Aborts on a {@code CR (';')}. */ ByteProcessor FIND_SEMI_COLON = new IndexOfProcessor((byte) ';'); /** * Aborts on a {@code CR ('\r')} or a {@code LF ('\n')}. */ ByteProcessor FIND_CRLF = new ByteProcessor() { @Override public boolean process(byte value) { return value != '\r' && value != '\n'; } }; /** * Aborts on a byte which is neither a {@code CR ('\r')} nor a {@code LF ('\n')}. */ ByteProcessor FIND_NON_CRLF = new ByteProcessor() { @Override public boolean process(byte value) { return value == '\r' || value == '\n'; } }; /** * Aborts on a linear whitespace (a ({@code ' '} or a {@code '\t'}). */ ByteProcessor FIND_LINEAR_WHITESPACE = new ByteProcessor() { @Override public boolean process(byte value) { return value != ' ' && value != '\t'; } }; /** * Aborts on a byte which is not a linear whitespace (neither {@code ' '} nor {@code '\t'}). */ ByteProcessor FIND_NON_LINEAR_WHITESPACE = new ByteProcessor() { @Override public boolean process(byte value) { return value == ' ' || value == '\t'; } }; /** * @return {@code true} if the processor wants to continue the loop and handle the next byte in the buffer. * {@code false} if the processor wants to stop handling bytes and abort the loop. */ boolean process(byte value) throws Exception; }
发表评论
-
netty NioSocketChannel解析
2017-09-29 12:50 1313netty 抽象BootStrap定义:http://dona ... -
netty Pooled字节buf分配器
2017-09-28 13:00 2051netty 字节buf定义:http://donald-dra ... -
netty Unpooled字节buf分配器
2017-09-26 22:01 2437netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf分配器
2017-09-26 08:43 1311netty 字节buf定义:http:// ... -
netty 复合buf概念
2017-09-25 22:31 1306netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf引用计数器
2017-09-22 12:48 1592netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf解析
2017-09-22 09:00 1842netty 通道接口定义:http://donald-drap ... -
netty 资源泄漏探测器
2017-09-21 09:37 1393netty 通道接口定义:http://donald-drap ... -
netty 默认通道配置后续
2017-09-18 08:36 2174netty 通道接口定义:http://donald-drap ... -
netty 默认通道配置初始化
2017-09-17 22:51 2033netty 通道接口定义:http://donald-drap ... -
netty 通道配置接口定义
2017-09-17 14:51 1077netty 通道接口定义:http://donald-drap ... -
netty NioServerSocketChannel解析
2017-09-16 13:01 1876netty ServerBootStrap解析:http:// ... -
netty 抽象nio消息通道
2017-09-15 15:30 1216netty 通道接口定义:http:/ ... -
netty 抽象nio字节通道
2017-09-14 22:39 1201netty 通道接口定义:http:/ ... -
netty 抽象nio通道解析
2017-09-14 17:23 955netty 通道接口定义:http://donald-drap ... -
netty 抽象通道后续
2017-09-13 22:40 1307netty Inboudn/Outbound通道Inv ... -
netty 通道Outbound缓冲区
2017-09-13 14:31 2188netty 通道接口定义:http:/ ... -
netty 抽象Unsafe定义
2017-09-12 21:24 1071netty 通道接口定义:http:/ ... -
netty 抽象通道初始化
2017-09-11 12:56 1851netty 管道线定义-ChannelPipeline:htt ... -
netty 通道接口定义
2017-09-10 15:36 1871netty Inboudn/Outbound通道Invoker ...
相关推荐
**字节序**定义了多字节数据在内存中的排列方式。有两种主要的字节序: - **Little-Endian**: 在这种格式下,低字节位于内存较低的位置,而高字节位于较高位置。例如,如果有一个整数`0x12345678`,在Little-Endian...
- 例如,在某些场景下,如果需要接收的数据量固定为 25 字节,而实际设置的是 50 字节,那么可以修改为只接收 25 字节。 - 此外,还需要注意操作系统当前的设置,确保与 LoadRunner 的配置相匹配。 #### 二、设置...
在 Java 中,将对象转换为 byte 数组是一种常见的操作,特别是在使用 Netty 进行通信协议传输的场景中。那么,如何方便地将一个 Java 对象构造成一个 byte 数组呢? 方法 1:使用 ByteBuf 在 Netty 中,我们可以...
电子商务之价格优化算法:梯度下降:机器学习在价格优化中的角色.docx
ToadforOracle与Oracle数据库版本兼容性教程.docx
360浏览器银河麒麟版 for X86 适配兆芯 / 海光 / intel / AMD CPU
使用React.js构建,提供多种主题可供选择,并且易于定制。该项目旨在帮助开发者和自由职业者创建自己的个性化投资组合。 主要功能点 多种主题可供选择,包括绿色、黑白、蓝色、红色、橙色、紫色、粉色和黄色 易于定制,可以在src/data文件夹中更新个人信息 包含主页、关于、简历、教育、技能、经验、项目、成就、服务、推荐信、博客和联系等多个部分 支持通过Google表单收集联系信息 提供SEO优化建议 支持多种部署方式,如Netlify、Firebase、Heroku和GitHub Pages 技术栈主要 React.js Material-UI Axios React-fast-marquee React-helmet React-icons React-reveal React-router-dom React-router-hash-link React-slick Slick-carousel Validator
中小型企业财务管理系统 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
电子商务之价格优化算法:线性回归:价格优化策略实施.docx
内容概要:报告详细介绍了企业数字化转型的驱动因素、数字化转型方案分类及其应用场景,重点关注了云计算、超连接、数字孪生、人工智能、分布式账本、增材制造、人机接口、数据共享、工业物联网等关键技术。这些技术不仅支持了企业的运营效率提升和业务模式创新,也为实现更快、更开放、更高效的数字化转型提供了支撑。报告最后提出了企业实施数字化转型的六个步骤。 适合人群:企业高级管理人员、技术人员、咨询顾问,以及对工业数字化转型感兴趣的读者。 使用场景及目标:帮助企业制定和实施数字化转型策略,优化运营模式,提升业务效率,增强市场竞争力。同时,也可作为政府部门、研究机构和行业协会的参考文献。 其他说明:报告中提到的关键技术及其应用场景对企业数字化转型具有重要的指导意义,特别是对于那些希望通过数字化转型实现业务创新和升级的企业。
基于java的线上选课系统的设计与实现答辩PPT.pptx
安装前的准备 1、安装Python:确保你的计算机上已经安装了Python。你可以在命令行中输入python --version或python3 --version来检查是否已安装以及安装的版本。 个人建议:在anaconda中自建不同python版本的环境,方法如下(其他版本照葫芦画瓢): 比如创建python3.8环境,anaconda命令终端输入:conda create -n py38 python==3.8 2、安装pip:pip是Python的包管理工具,用于安装和管理Python包。你可以通过输入pip --version或pip3 --version来检查pip是否已安装。 安装WHL安装包 1、打开命令行(或打开anaconda命令行终端): 在Windows上,你可以搜索“cmd”或“命令提示符”并打开它。 在macOS或Linux上,你可以打开“终端”。 2、cd到whl文件所在目录安装: 使用cd命令导航到你下载的whl文件所在的文件夹。 终端输入:pip install xxx.whl安装即可(xxx.whl指的是csdn下载解压出来的whl) 3、等待安装完成: 命令行会显示安装进度,并在安装完成后返回提示符。 以上是简单安装介绍,小白也能会,简单好用,从此再也不怕下载安装超时问题。 使用过程遇到问题可以私信,我可以帮你解决! 收起
电子商务之价格优化算法:贝叶斯定价:贝叶斯网络在电子商务定价中的应用.docx
IMG_20241105_235746.jpg
基于java的毕业设计选题系统答辩PPT.pptx
专升本考试资料全套.7z
Trustwave DbProtect:数据库活动监控策略制定.docx
基于VB的程序实例,可供参考学习使用
本压缩包资源说明,你现在往下拉可以看到压缩包内容目录 我是批量上传的基于SpringBoot+Vue的项目,所以描述都一样;有源码有数据库脚本,系统都是测试过可运行的,看文件名即可区分项目~ |Java|SpringBoot|Vue|前后端分离| 开发语言:Java 框架:SpringBoot,Vue JDK版本:JDK1.8 数据库:MySQL 5.7+(推荐5.7,8.0也可以) 数据库工具:Navicat 开发软件: idea/eclipse(推荐idea) Maven包:Maven3.3.9+ 系统环境:Windows/Mac