Netty-内存池源码一 (内存分配入口)
当 Client 向 Server 发送请求, 此时Server端的 【NioSocketChannel
】 则会响应 【readOps
】 事件。而在处理该事件时, 需要使用ByteBuf , 那么目标就指向:
【AbstractNioByteChannel #NioByteUnsafe # read()
】
public final void read() {
//.....省略
// #1. 获取 池化内存缓冲区分配器
final ByteBufAllocator allocator = config.getAllocator();
// #2. 获取 缓冲区大小预测器
final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
ByteBuf byteBuf = null;
boolean close = false;
try {
do {
//#3. 分配出一块内存 byteBuf
byteBuf = allocHandle.allocate(allocator);
} while (allocHandle.continueReading());
} // .....省略
}
从代码看 allocator
就是 分配Netty 用来分配内存的大佬, 那么 该池化内存缓冲区分配器是谁?
-
#1 final ByteBufAllocator allocator = config.getAllocator();
跟随 config.getAllocator() 可知,该allocator 是由 【
ByteBufUtil
】工具类获取的,代码如下ByteBufAllocator allocator = ByteBufUtil.DEFAULT_ALLOCATOR;
进入【
ByteBufUtil
】, 其中有段关键的代码// 当前平台若是Android 内存分配器则使用 unpooled, 若不是则使用 pooled String allocType = SystemPropertyUtil.get( "io.netty.allocator.type", PlatformDependent.isAndroid() ? "unpooled" : "pooled"); ByteBufAllocator alloc; if ("unpooled".equals(allocType)) { alloc = UnpooledByteBufAllocator.DEFAULT; logger.debug("-Dio.netty.allocator.type: {}", allocType); } else if ("pooled".equals(allocType)) { // 默认会使用 该内存分配器 PooledByteBufAllocator 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;
从上面代码可知, 默认普通情况下 内存分配器就是 【
PooledByteBufAllocator
】 -
#3 byteBuf = allocHandle.allocate(allocator);
下面跟踪该分配方法:=> 1.【
DefaultMaxMessagesRecvByteBufAllocator #MaxMessageHandle #allocate()
】:alloc.ioBuffer(guess());
=> 2.【
AbstractByteBufAllocator #ioBuffer()
】:directBuffer(initialCapacity);
这里我们默认使用直接内存。=> 3. 【
AbstractByteBufAllocator #directBuffer()
】:newDirectBuffer(initialCapacity, maxCapacity);
=> 4. 最终会来到 【
PooledByteBufAllocator #newDirectBuffer()
】 该方法就是申请分配内存的入口