一、ByteBuf的结构:
1.结构图:
从上图可以看出,该结构是一个字节容器,里面的数据分为三部分,第一部分是已经丢弃的字节,这部分的数据是无效的,第二部分是可读字节,这部分数据是该结构的主题数据,最后一部分为可写字节,后面虚线部分表示该结构还可以扩容多少
具体分析,该结构包括两个指针,分别是读指针和写指针,每读一个字节,readerinsex就自增1,其中总共有writeIndex-readerIndex个字节可读,由此,当读写指针指向一个位置时表示不可读,写指针同理,但是该指针是当其增加到capacity时表示不可写
另外,当该结构写数据时容量不足时会自动进行扩容,如果容器真实的容量大小和最大容量大小(maxCapacity)相等时就会暂停,超过之后就不报错
2.容量API
capacity():表示bytebuf底层占用了多少字节
maxcapacity():表示该结构底层最多能够占用多大的字节的内存
readableBytes()与isReadable():分别表示当前可读的字节和是否可读,即读写指针是否一致,一致则isReadable()会返回false
writeableBytes() iswriteable() maxWriteable():分别表示当前可写的数据,以及是否可写和当前可写的最大字节数
3.读写指针相关的API
readerIndex() readerIndex(int):前者返回当前的读指针,后者表示设置读指针
writeIndex() writeIndex(int):前者表示返回写指针,后者表示设置写指针
markReaderIndex() resetReaderIndex():前者表示保存当前的读指针,后者表示把当前的读指针恢复到之前保存的值
markWriterIndex() resetWriterIndex():同理read相关的API
4.读写API
writeBytes(bytes[] src) buffer.readBytes(byte[] dst): 前者表示把字节数组src里面的数据全部写到ByteBuf中,后者时把ByteBuf中的数据全部读取到dst中,其大小为readableBytes()
release()与retain():因为Netty使用的是堆外内存并且是不被jvm直接管理申请到的内存无法被垃圾回收器直接回收,需要手动回收,否则会造成内存泄漏
slice() duplicate() copy():第一个方法是截取readerIndex到writeIndex之间,并且返回的ByteBuf的最大容量是原始的readableBytes(),第二个方法是把整个ByteBuf都截取出来,前两个方法的相同点是底层是与原始的ByteBuf共享,即经过返回的ByteBuf的对象调用write方法都会影响到原始的ByteBuf,但是它们维持的与原始的读写指针不同的指针,最后一个方法会直接从原始的ByteBuf中复制信息
retainedSlice() retainedDuplicate():这两个方法的作用是截取内存片段的同时会增加内存的引用计数
5.示例代码:
java"> public class ByteBufTest {
public static void main(String[] args) {
ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(9, 100);
print("allocate ByteBuf(9, 100)", buffer);
// write方法改变写指针,写完之后写指针未到capacity的时候,
buffer仍然可写
buffer.writeBytes(new byte[]{1, 2, 3, 4});
print("writeBytes(1,2,3,4)", buffer);
// write方法改变写指针,写完之后写指针未到capacity的时候,
buffer仍然可写,写完int
类型之后,写指针增加4
buffer.writeInt(12);
print("writeInt(12)", buffer);
// write方法改变写指针,写完之后写指针等于capacity的时候,
buffer不可写
buffer.writeBytes(new byte[]{5});
print("writeBytes(5)", buffer);
// write方法改变写指针,写的时候发现buffer不可写则开始扩容,扩容
之后capacity随即改变
buffer.writeBytes(new byte[]{6});
print("writeBytes(6)", buffer);
// get方法不改变读写指针
System.out.println("getByte(3) return: " + buffer.getByte(3));
System.out.println("getShort(3) return: " + buffer.getShort(3));
System.out.println("getInt(3) return: " + buffer.getInt(3));
print("getByte()", buffer);
// set方法不改变读写指针
buffer.setByte(buffer.readableBytes() + 1, 0);
print("setByte()", buffer);
// read方法改变读指针
byte[] dst = new byte[buffer.readableBytes()];
buffer.readBytes(dst);
print("readBytes(" + dst.length + ")", buffer);
}
private static void print(String action, ByteBuf buffer) {
System.out.println("after ===========" + action + "============
");
System.out.println("capacity(): " + buffer.capacity());
System.out.println("maxCapacity(): " + buffer.maxCapacity());
System.out.println("readerIndex(): " + buffer.readerIndex());
System.out.println("readableBytes(): " + buffer.readableBytes());
System.out.println("isReadable(): " + buffer.isReadable());
System.out.println("writerIndex(): " + buffer.writerIndex());
System.out.println("writableBytes(): " + buffer.writableBytes());
System.out.println("isWritable(): " + buffer.isWritable());
System.out.println("maxWritableBytes(): " + buffer.maxWritableByte
s());
System.out.println();
}
}