NOTE
2.82 ByteBuf
数据结构 有两个指针,一个标记读的位置,一个标记写的位置。 0 < 读 < 写 < capacity 其中0到读之间的数据是无效的,读到写之间的数据是可读的,写到capacity之间是可写的 Api readXXX表示读数据,读指针往后移动 writeXXX表示写数据,写指针往后移动 set不移动指
这是历史学习笔记,可能存在过时或不完整的理解。
数据结构
有两个指针,一个标记读的位置,一个标记写的位置。
0 < 读 < 写 < capacity
其中0到读之间的数据是无效的,读到写之间的数据是可读的,写到capacity之间是可写的
Api
readXXX表示读数据,读指针往后移动 writeXXX表示写数据,写指针往后移动 set不移动指针,只是改变数据
mark记录当前读指针的位置,将来可以通过reset回溯
类体系
ByteBuf都是一些抽象的方法
而AbstractByteBuf则是提供了一些基础骨架的实现
- 比如getByte 就是检查了下索引是否正确,然后调用子类实现的getByte
@Override
public byte getByte(int index) {
checkIndex(index);
return _getByte(index);
}
protected abstract byte _getByte(int index);
分类
主要可以按照三个维度分类
pooled和unpooled
操作数据是否在预先分配的内存中的
unsafe和非unsafe
是否使用了jdk底层的nio进行操作
我们以PooledUnsafeHeapByteBuf为例,看看他的_getByte方法
protected byte _getByte(int index) {
return UnsafeByteBufUtil.getByte(memory, idx(index));
}
static byte getByte(byte[] array, int index) {
return PlatformDependent.getByte(array, index);
}
public static byte getByte(byte[] data, int index) {
return PlatformDependent0.getByte(data, index);
}
static byte getByte(byte[] data, int index) {
//最后调用了Unsafe
return UNSAFE.getByte(data, BYTE_ARRAY_BASE_OFFSET + index);
}
再对比PooledHeapByteBuf的_getByte
protected byte _getByte(int index) {
return HeapByteBufUtil.getByte(memory, idx(index));
}
static byte getByte(byte[] memory, int index) {
//没有调用unsafe,直接数组读取
return memory[index];
}
heap和direct
内存是在jvm堆上还是直接才OS内存上分配的
我们以UnPooledHeapByteBuf的getByte为例
public byte getByte(int index) {
ensureAccessible();
return _getByte(index);
}
protected byte _getByte(int index) {
return HeapByteBufUtil.getByte(array, index);
}
static byte getByte(byte[] memory, int index) {
//再数组上读取,说明是在堆上
return memory[index];
}
对比UnPooledDirectByteBuf
public byte getByte(int index) {
ensureAccessible();
return _getByte(index);
}
protected byte _getByte(int index) {
//这个buffer是jdk nio的buffer
//可以看看Unpooled的directBuffer
return buffer.get(index);
}
- Unpooled的directBuffer
public static ByteBuf directBuffer(int initialCapacity) {
return ALLOC.directBuffer(initialCapacity);
}
public ByteBuf directBuffer(int initialCapacity) {
return directBuffer(initialCapacity, DEFAULT_MAX_CAPACITY);
}
public ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
if (initialCapacity == 0 && maxCapacity == 0) {
return emptyBuf;
}
validate(initialCapacity, maxCapacity);
return newDirectBuffer(initialCapacity, maxCapacity);
}
protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
final ByteBuf buf;
if (PlatformDependent.hasUnsafe()) {
//这里
buf = noCleaner ? new InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf(this, initialCapacity, maxCapacity) :
new InstrumentedUnpooledUnsafeDirectByteBuf(this, initialCapacity, maxCapacity);
} else {
buf = new InstrumentedUnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
}
return disableLeakDetector ? buf : toLeakAwareBuffer(buf);
}
//。。。。
public UnpooledUnsafeDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
super(maxCapacity);
if (alloc == null) {
throw new NullPointerException("alloc");
}
if (initialCapacity < 0) {
throw new IllegalArgumentException("initialCapacity: " + initialCapacity);
}
if (maxCapacity < 0) {
throw new IllegalArgumentException("maxCapacity: " + maxCapacity);
}
if (initialCapacity > maxCapacity) {
throw new IllegalArgumentException(String.format(
"initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
}
this.alloc = alloc;
//ByteBuffer.allocateDirect(initialCapacity)
//jdk底层nio分配直接内存
setByteBuffer(allocateDirect(initialCapacity), false);
}