1. 概述
本文,我们来分享 ByteBufAllocator 。它是 ByteBuf 的分配器,负责创建 ByteBuf 对象。它的子类类图如下:类图
主要有三个子类:
- PreferHeapByteBufAllocator ,倾向创建 Heap ByteBuf 的分配器。
- PooledByteBufAllocator ,基于内存池的 ByteBuf 的分配器。
- UnpooledByteBufAllocator ,普通的 ByteBuf 的分配器。
本文分享上面类图红框部分,后面两篇文章再分别分享 UnpooledByteBufAllocator 和 PooledByteBufAllocator 。
2. ByteBufAllocator
io.netty.buffer.ByteBufAllocator
,ByteBuf 分配器接口。
还是老样子,我们逐个来看看每个方法。
2.1 DEFAULT
ByteBufAllocator DEFAULT = ByteBufUtil.DEFAULT_ALLOCATOR; |
默认 ByteBufAllocator 对象,通过
ByteBufUtil.DEFAULT_ALLOCATOR
中获得。代码如下:static final ByteBufAllocator DEFAULT_ALLOCATOR;
static {
// 读取 ByteBufAllocator 配置
String allocType = SystemPropertyUtil.get("io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled");
allocType = allocType.toLowerCase(Locale.US).trim();
// 读取 ByteBufAllocator 对象
ByteBufAllocator alloc;
if ("unpooled".equals(allocType)) {
alloc = UnpooledByteBufAllocator.DEFAULT;
logger.debug("-Dio.netty.allocator.type: {}", allocType);
} else if ("pooled".equals(allocType)) {
alloc = PooledByteBufAllocator.DEFAULT;
logger.debug("-Dio.netty.allocator.type: {}", allocType);
} else {
alloc = PooledByteBufAllocator.DEFAULT;
logger.debug("-Dio.netty.allocator.type: pooled (unknown: {})", allocType);
}
DEFAULT_ALLOCATOR = alloc;
// ... 省略无关代码
}- 在非 Android 环境下,使用 PooledByteBufAllocator 作为默认 ByteBufAllocator 对象。
- 在 Android 环境下,使用 UnpooledByteBufAllocator 作为默认 ByteBufAllocator 对象。因为 Android 客户端的内存相对有限。
2.2 buffer
#buffer(...)
方法,创建一个 ByteBuf 对象。具体创建的是 Heap ByteBuf 还是 Direct ByteBuf ,由实现类决定。
/** |
2.2.1 ioBuffer
#ioBuffer(...)
方法,创建一个用于 IO 操作的 ByteBuf 对象。倾向于 Direct ByteBuf ,因为对于 IO 操作来说,性能更优。
/** |
2.2.2 heapBuffer
#heapBuffer(...)
方法,创建一个 Heap Buffer 对象。代码如下:
/** |
2.2.3 directBuffer
#directBuffer(...)
方法,创建一个 Direct Buffer 对象。代码如下:
/** |
2.3 compositeBuffer
#compositeBuffer(...)
方法,创建一个 Composite ByteBuf 对象。具体创建的是 Heap ByteBuf 还是 Direct ByteBuf ,由实现类决定。
/** |
2.3.1 compositeHeapBuffer
#compositeHeapBuffer(...)
方法,创建一个 Composite Heap ByteBuf 对象。代码如下:
/** |
2.3.2 compositeDirectBuffer
#compositeDirectBuffer(...)
方法,创建一个 Composite Direct ByteBuf 对象。代码如下:
/** |
2.4 isDirectBufferPooled
#isDirectBufferPooled()
方法,是否基于 Direct ByteBuf 对象池。代码如下:
/** |
2.5 calculateNewCapacity
#calculateNewCapacity(int minNewCapacity, int maxCapacity)
方法,在 ByteBuf 扩容时,计算新的容量,该容量的值在 [minNewCapacity, maxCapacity]
范围内。代码如下:
/** |
3. AbstractByteBufAllocator
io.netty.buffer.AbstractByteBufAllocator
,实现 ByteBufAllocator 接口,ByteBufAllocator 抽象实现类,为 PooledByteBufAllocator 和 UnpooledByteBufAllocator 提供公共的方法。
3.1 构造方法
/** |
directByDefault
属性,是否倾向创建 Direct ByteBuf 。有一个前提是需要支持 Unsafe 操作。emptyBuf
属性,空 ByteBuf 缓存对象。用于#buffer()
等方法,创建空 ByteBuf 对象时。
3.2 buffer
|
- 根据
directByDefault
的值,调用#directBuffer(...)
方法,还是调用#heapBuffer(...)
方法。
3.2.1 ioBuffer
/** |
- 根据是否支持 Unsafe 操作的情况,调用
#directBuffer(...)
方法,还是调用#heapBuffer(...)
方法。
3.2.2 heapBuffer
/** |
最终调用
#newHeapBuffer(int initialCapacity, int maxCapacity)
抽象方法,创建 Heap ByteBuf 对象。代码如下:/**
* Create a heap {@link ByteBuf} with the given initialCapacity and maxCapacity.
*/
protected abstract ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity);- 因为是否基于对象池的方式,创建 Heap ByteBuf 对象的实现会不同,所以需要抽象。
3.2.3 directBuffer
|
最终调用
#newDirectBuffer(int initialCapacity, int maxCapacity)
抽象方法,创建 Direct ByteBuf 对象。代码如下:/**
* Create a direct {@link ByteBuf} with the given initialCapacity and maxCapacity.
*/
protected abstract ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity);- 因为是否基于对象池的方式,创建 Direct ByteBuf 对象的实现会不同,所以需要抽象。
3.3 compositeBuffer
|
- 根据
directByDefault
的值,调用#compositeDirectBuffer(...)
方法,还是调用#compositeHeapBuffer(...)
方法。
3.3.1 compositeHeapBuffer
/** |
- 创建 CompositeByteBuf 对象,并且方法参数
direct
为false
,表示 Heap 类型。 - 调用
#toLeakAwareBuffer(CompositeByteBuf)
方法,装饰成 LeakAware 的 ByteBuf 对象。
3.3.2 compositeDirectBuffer
|
- 创建 CompositeByteBuf 对象,并且方法参数
direct
为true
,表示 Direct 类型。 - 调用
#toLeakAwareBuffer(CompositeByteBuf)
方法,装饰成 LeakAware 的 ByteBuf 对象。
3.4 toLeakAwareBuffer
在 《精尽 Netty 源码解析 —— Buffer 之 ByteBuf(三)内存泄露检测》 中的 「3.1 创建 LeakAware ByteBuf 对象」 小节,已经详细解析。
3.5 calculateNewCapacity
/** |
- 按照
CALCULATE_THRESHOLD
作为分界线,分成 3 种情况:<1>
/<2>
/<3>
。代码比较简单,胖友自己看注释。
4. PreferHeapByteBufAllocator
io.netty.channel.PreferHeapByteBufAllocator
,实现 ByteBufAllocator 接口,倾向创建 Heap ByteBuf 的分配器。也就是说,#buffer(...)
和 #ioBuffer(...)
和 #compositeBuffer(...)
方法,创建的都是 Heap ByteBuf 对象。代码如下:
/** |
其它方法,就是调用 allocator
的对应的方法。
666. 彩蛋
😈 小水文一篇。铺垫铺垫,你懂的。