ByteBuf的分配
一. ByteBufAllocator 池类
可分配基于堆的或者直接内存的ByteBuf
获得ByteBufAllocator引用的的两种方式:
channel.alloc();
ctx.alloc();
ByteBufAllocator的两种实现:
PooledByteBufAllocator
UnpooledByteBufAllocator
二.Unpooled 非池化的Bytebuf
三.ByteBufUtil
ByteBuf 和 ByteBufHolder
ByteBuf的主要有读写两个指针,这是他比原生ByteBuffer方便和易于理解的地方 read*, write开头的方法会改变索引,但是set将不会改变索引位置 |**** 版本号 4个字节的长度 具体的内容****|
ByteBuf 的使用模式
- 堆缓冲区(基于数组实现的)
所以可以通过hasArray判断是否支持数组
ByteBuf heapBuf = ...;
if (heapBuf.hasArray()) { //1
byte[] array = heapBuf.array(); //2
int offset = heapBuf.arrayOffset() + heapBuf.readerIndex(); //3
int length = heapBuf.readableBytes();//4
handleArray(array, offset, length); //5
}
- 直接缓冲区
ByteBuf directBuf = ...
if (!directBuf.hasArray()) { //1
int length = directBuf.readableBytes();//2
byte[] array = new byte[length]; //3
directBuf.getBytes(directBuf.readerIndex(), array); //4
handleArray(array, 0, length); //5
}
-
复合缓冲区(CompositeByteBuf )
hasArray始终返回false
CompositeByteBuf messageBuf = ...;
ByteBuf headerBuf = ...; // 可以支持或直接
ByteBuf bodyBuf = ...; // 可以支持或直接
messageBuf.addComponents(headerBuf, bodyBuf);
// ....
messageBuf.removeComponent(0); // 移除头 //2
for (int i = 0; i < messageBuf.numComponents(); i++) { //3
System.out.println(messageBuf.component(i).toString());
}
访问数据
CompositeByteBuf compBuf = ...;
int length = compBuf.readableBytes(); //1
byte[] array = new byte[length]; //2
compBuf.getBytes(compBuf.readerIndex(), array); //3
handleArray(array, 0, length); //4
随机访问索引: 如getByte,不会改变索引 可丢弃的字节重新利用: discardReadBytes(); 索引操作: markWriterIndex() markReaderIndex() resetReaderIndex() resetWriterIndex() clear() 比 discardReadBytes()成本更低 查询操作: forEachByte int index = buffer.forEachByte(ByteBufProcessor.FIND_CR); forEachByte(ByteBufProcessor.FIND_NUL) 衍生的缓冲区: 代表一个专门的展示 ByteBuf 内容的“视图" 这种视图由下面几种方法产生 duplicate(), slice(), slice(int, int),readOnly(),order(ByteOrder) 这种视图和源是数据共享的吗? 读写索引是一样的吗? 标记索引是一样的吗? 答:都是共享的
拷贝: copy()和copy(int, int) 这个副本是独立的, 和源数据不共享 需要某段数据: slice(int, int) 和源数据是共享的 读写操作: set写入/get读取不会改变索引 write/read