ByteBuf源码分析
分配原理
简单结构图
[0, readerIndex)
此区间表示当前已经丢弃的数据,不可再读,也不能再利用;[readerIndex, writerIndex)
此区间表示当前可读取到的数据;[writerIndex, capacity)
此区间表示当前可以写入的范围[capacity, maxCapacity]
此区间表示可扩容的范围
进阶版结构图
[initial, markReaderIndex)
此区间的数据已经被丢弃,无法重利用[markerReaderIndex, readerIndex)
此区间的数据表示可以重利用[readerIndex, writerIndex)
此区间表示当前可读到的数据[markerWriterIndex, writerIndex)
此区间的数据表示可以丢弃,可以再次进行覆盖写入[writerIndex, capacity)
此区间表示可以写入的范围[capacity, maxCapacity]
此区间表示可扩容的范围
附一张源码中截图
类图
比较繁多,这里只列举关键的、常用的几种类
- 内存对象是否池化;Pooled,Unpooled
- 内存对象是否通过Unsafe接口提供的地址指针进行操作;
- 内存对象保存的堆外、堆内内存;Direct、Heap
- 是否组合,Composite
常见操作
1、 getXX
作用:获取指定位置的数据
有getByte、getInt、getLong等; 以getByte为例;在AbstractByteBuf中定义_getByte()
方法抽象,由具体的子类进行根据不同的行为来实现;
比如:UnpooledHeapByteBuf._getByte()
是通过HeapByteBufUtil直接通过索引才进行查找
java
protected byte _getByte(int index) {
return HeapByteBufUtil.getByte(array, index);
}
// io.netty.buffer.HeapByteBufUtil#getByte
static byte getByte(byte[] memory, int index) {
return memory[index];
}
再比如:UnpooledDirectByteBuf._getByte()
直接调用DirectByteBuffer来进行查找的
arduino
protected byte _getByte(int index) {
return buffer.get(index);
}
再比如:UnpooledUnsafeDirectByteBuf._getByte()
是通过DirectByteBufUtil,通过Unsafe API的方式,利用内存地址进行快速索引;(跳过了DirectByteBuffer接口)
java
protected byte _getByte(int index) {
return UnsafeByteBufUtil.getByte(addr(index));
}
// after some invokes
......
static byte getByte(long address) {
return UNSAFE.getByte(address);
}
2、 writeXX
作用: 写入一些内容;
布局思想:write和get类型,
3、 setXX
作用:在指定位置,写入一些元素;
使用手册
通过ByteBufAllocator进行分配;
PooledByteBufAllocator
- 可以分配池化的对象;
- 通过调用directBuffer、headBuffer方法进行分配
UnpooledByteBufAllocator
- 分配非池化对象
- 调用directBuffer、heapBuffer方法决定在哪块内存上进行分配
至于ByteBufAllocator如何进行分配,且听下期分享