ByteBuf:是数据容器(字节容器)
JDK ByteBuffer
共用读写索引,每次读写操作都需要Flip()
扩容麻烦,而且扩容后容易造成浪费 关于ByteBuffer的使用方法可以参考[序列化和反序列化的三种方法 ](https://my.oschina.net/u/3768341/blog/1815513),里面有Netty 3的ChannelBuffer,因为现在Netty 3用的比较少,当作参考就好。
Netty ByteBuf
读写使用不同的索引,所以操作便捷
自动扩容,使用便捷
我们现在来看一下ByteBuf的源码。
public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf>
我们可以看到ByteBuf是一个抽象类,它里面几乎大部分都是抽象方法。
继承ByteBuf的是一个AbstractByteBuf的抽象类,而读写索引的属性就在该类中。
public abstract class AbstractByteBuf extends ByteBuf
int readerIndex; //读索引
int writerIndex; //写索引
private int markedReaderIndex; //标记当前读索引的位置
private int markedWriterIndex; //标记当前写索引的位置
private int maxCapacity; //最大容量
而支持自动扩容的部分可以由ensureWritable追踪看到
@Override
public ByteBuf ensureWritable(int minWritableBytes) {
if (minWritableBytes < 0) {
throw new IllegalArgumentException(String.format(
"minWritableBytes: %d (expected: >= 0)", minWritableBytes));
}
ensureWritable0(minWritableBytes);
return this;
}
final void ensureWritable0(int minWritableBytes) {
ensureAccessible();
if (minWritableBytes <= writableBytes()) {
return;
}
if (minWritableBytes > maxCapacity - writerIndex) {
throw new IndexOutOfBoundsException(String.format(
"writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",
writerIndex, minWritableBytes, maxCapacity, this));
}
// Normalize the current capacity to the power of 2.
int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);
// Adjust to the new capacity.
capacity(newCapacity);
}
在AbstractByteBufAllocator中
static final int CALCULATE_THRESHOLD = 1048576 * 4; // 4 MiB page
/**
* 计算新容量
*/
@Override
public int calculateNewCapacity(int minNewCapacity, int maxCapacity) {
if (minNewCapacity < 0) {
throw new IllegalArgumentException("minNewCapacity: " + minNewCapacity + " (expected: 0+)");
}
if (minNewCapacity > maxCapacity) {
throw new IllegalArgumentException(String.format(
"minNewCapacity: %d (expected: not greater than maxCapacity(%d)",
minNewCapacity, maxCapacity));
}
final int threshold = CALCULATE_THRESHOLD; // 4 MiB page
if (minNewCapacity == threshold) {
return threshold;
}
// If over threshold, do not double but just increase by threshold.
if (minNewCapacity > threshold) {
int newCapacity = minNewCapacity / threshold * threshold;
if (newCapacity > maxCapacity - threshold) {
newCapacity = maxCapacity;
} else {
newCapacity += threshold;
}
return newCapacity;
}
// Not over threshold. Double up to 4 MiB, starting from 64.
int newCapacity = 64;
while (newCapacity < minNewCapacity) {
newCapacity <<= 1;
}
return Math.min(newCapacity, maxCapacity);
}
这个newCapacity就是扩容的新容量,所以我们一般不需要担心ByteBuf容量不够的问题。