- 浏览: 980961 次
文章分类
- 全部博客 (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 1321netty 抽象BootStrap定义:http://dona ... -
netty Pooled字节buf分配器
2017-09-28 13:00 2057netty 字节buf定义:http://donald-dra ... -
netty Unpooled字节buf分配器
2017-09-26 22:01 2444netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf分配器
2017-09-26 08:43 1316netty 字节buf定义:http:// ... -
netty 复合buf概念
2017-09-25 22:31 1310netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf引用计数器
2017-09-22 12:48 1593netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf解析
2017-09-22 09:00 1844netty 通道接口定义:http://donald-drap ... -
netty 资源泄漏探测器
2017-09-21 09:37 1397netty 通道接口定义:http://donald-drap ... -
netty 默认通道配置后续
2017-09-18 08:36 2177netty 通道接口定义:http://donald-drap ... -
netty 默认通道配置初始化
2017-09-17 22:51 2036netty 通道接口定义:http://donald-drap ... -
netty 通道配置接口定义
2017-09-17 14:51 1078netty 通道接口定义:http://donald-drap ... -
netty NioServerSocketChannel解析
2017-09-16 13:01 1877netty ServerBootStrap解析:http:// ... -
netty 抽象nio消息通道
2017-09-15 15:30 1217netty 通道接口定义:http:/ ... -
netty 抽象nio字节通道
2017-09-14 22:39 1201netty 通道接口定义:http:/ ... -
netty 抽象nio通道解析
2017-09-14 17:23 957netty 通道接口定义:http://donald-drap ... -
netty 抽象通道后续
2017-09-13 22:40 1309netty Inboudn/Outbound通道Inv ... -
netty 通道Outbound缓冲区
2017-09-13 14:31 2189netty 通道接口定义:http:/ ... -
netty 抽象Unsafe定义
2017-09-12 21:24 1076netty 通道接口定义:http:/ ... -
netty 抽象通道初始化
2017-09-11 12:56 1855netty 管道线定义-ChannelPipeline:htt ... -
netty 通道接口定义
2017-09-10 15:36 1876netty Inboudn/Outbound通道Invoker ...
相关推荐
在Java编程环境中,Netty是一个高性能、异步事件驱动的网络应用程序框架,常用于构建可伸缩、高并发的服务器。本示例关注的是如何利用Netty实现一个基于UDP(User Datagram Protocol)的数据接收服务,这在需要进行...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。在本文中,我们将深入探讨如何利用 Netty 4 构建基于 UDP(用户数据报协议)的数据接收服务,以及如何实现...
1. **字符编码与字节流**:在计算机系统中,字符和字节的对应关系是由字符编码(如ASCII、UTF-8、GBK等)定义的。不同的编码方式会导致相同的字符表示为不同的字节序列,如果在发送端和接收端使用了不同的编码方式,...
netty通信时经常和底层数据交互,C语言和java的数据类型和范围不同,通信时需要转化或兼容,附件为字节码、进制常用的转换类。
在 Netty 中,数据传输通常涉及 ByteBuf,这是 Netty 提供的高效字节缓冲区。ByteBuf 可以动态调整容量,支持读写索引,使得在网络编程中更加灵活和高效。 此外,Netty 还提供了多种编解码器,如 ...
分析这个代码,我们可以看到Netty如何创建服务器、设置管道、以及如何定义和使用自定义的解码器和编码器来处理16进制数据。 通过上述步骤,Netty服务器可以轻松地解析16进制数据,从而支持各种网络协议,无论它们是...
Netty提供了一种灵活的方式来定义自定义的编解码器,允许我们创建复杂的消息协议。这些编解码器可以将网络数据流转换为应用程序可理解的对象,反之亦然。例如,你可以创建一个特定的协议头解析器来识别协议头,并将...
- 使用 Netty 创建 WebSocket 服务器,首先需要定义一个 ChannelInitializer,配置处理 WebSocket 数据的 ChannelHandler。例如,WebSocketFrameDecoder 和 WebSocketFrameEncoder 用于解码和编码 WebSocket 帧。 ...
首先,TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,它确保了数据包的顺序和完整性。在C++中,我们可以使用标准库中的`<sys/socket.h>`和`<netinet/in.h>`来创建和管理socket,进行...
在基于Netty编写的socket服务端中,首先需要定义一个`ChannelHandler`,这个处理器负责处理接收到的网络事件,如连接建立、数据读取、连接关闭等。`ChannelHandlerContext`则是`ChannelHandler`和`ChannelPipeline`...
- ByteBuf是Netty的缓冲区,提供了高效的字节操作和内存管理。 7. **Netty-all-4.1.25.Final.jar**: - 这个jar包是Netty的全功能集,包含了Netty所有模块的类和依赖,适用于快速搭建项目,避免单独导入多个jar包...
2. **高效性**:Netty通过减少对象创建和内存复制来优化性能,例如,它的ByteBuf类提供了高效的字节缓冲区管理。 3. **灵活性**:Netty支持多种网络协议,如TCP、UDP、HTTP、WebSocket、FTP等,以及自定义协议。它...
3. **ByteBuf**:Netty提供的ByteBuf作为字节缓冲区,比Java的ByteBuffer更加灵活和高效。它支持读写指针独立移动,避免了不必要的内存复制。 4. **Pipeline**:Netty的ChannelHandler链是通过Pipeline实现的。...
《Netty实战》这本书是针对Java网络编程框架Netty的一本深入实践教程,旨在帮助读者掌握Netty的核心特性和实际应用。Netty是一款高性能、异步事件驱动的网络应用程序框架,广泛应用于各种分布式系统、微服务架构以及...
- **ByteBuf**:Netty自定义的高效字节缓冲区,比Java的ByteBuffer更易用且性能更好。 - **ChannelHandler**:处理器接口,用于实现I/O事件的处理逻辑。 - **Bootstrap**:启动器,用于配置并启动服务器或客户端...
Netty基础,用于学习Netty,参考黑马程序员的netty教程
通常,我们还需要添加预定义的处理器,如 ByteToMessageDecoder 和 MessageToByteEncoder,以处理基础的字节流转换。 3. **启动 ServerBootstrap**:在服务器端,使用 ServerBootstrap 绑定一个端口,监听连接请求...
《Netty实战》是针对Java开发者的一本技术指南,它深入介绍了如何利用Netty这个高性能、异步事件驱动的网络应用程序框架来构建高效且可扩展的网络应用。Netty不仅简化了网络编程的复杂性,还提供了丰富的特性和组件...
《跟闪电侠学Netty:Netty即时聊天实战与底层原理》是一本深入浅出的Netty技术指南,旨在帮助读者掌握Netty框架,并利用它实现即时聊天应用,同时理解其底层工作原理。Netty是Java领域的一款高性能、异步事件驱动的...
还会介绍如何定义自定义的编码解码器来处理特定的协议格式。对于协议解析,Netty提供了零拷贝机制,能有效减少内存复制,提高效率。 除此之外,Netty还提供了强大的心跳检测机制,可以防止因网络延迟或故障导致的...