PooledByteBufAllocator 源码深度解析
一、类的定位和继承关系
public class PooledByteBufAllocator extends AbstractByteBufAllocator
implements ByteBufAllocatorMetricProvider
继承关系:
AbstractByteBufAllocator:提供基础的分配逻辑ByteBufAllocatorMetricProvider:提供监控指标接口
作用:
- Netty 内存池的总管理者
- 管理所有的 Arena(内存区域)
- 管理所有的 ThreadCache(线程本地缓存)
- 提供统一的内存分配入口
二、静态常量(默认配置)
2.1 核心配置常量
// Arena 数量
private static final int DEFAULT_NUM_HEAP_ARENA; // 堆内存 Arena 数量
private static final int DEFAULT_NUM_DIRECT_ARENA; // 直接内存 Arena 数量
// Chunk 配置
private static final int DEFAULT_PAGE_SIZE; // Page 大小,默认 8KB
private static final int DEFAULT_MAX_ORDER; // 最大深度,默认 11
// ChunkSize = 8192 << 11 = 16 MiB
// ThreadCache 缓存大小
private static final int DEFAULT_TINY_CACHE_SIZE; // Tiny 缓存,默认 512
private static final int DEFAULT_SMALL_CACHE_SIZE; // Small 缓存,默认 256
private static final int DEFAULT_NORMAL_CACHE_SIZE; // Normal 缓存,默认 64
// 其他配置
private static final int DEFAULT_MAX_CACHED_BUFFER_CAPACITY; // 最大缓存容量,32KB
private static final int DEFAULT_CACHE_TRIM_INTERVAL; // 缓存清理间隔,8192 次
private static final long DEFAULT_CACHE_TRIM_INTERVAL_MILLIS; // 缓存清理时间间隔
private static final boolean DEFAULT_USE_CACHE_FOR_ALL_THREADS; // 是否所有线程使用缓存
2.2 边界值常量
private static final int MIN_PAGE_SIZE = 4096; // 最小 Page 大小 4KB
private static final int MAX_CHUNK_SIZE = (int) (((long) Integer.MAX_VALUE + 1) / 2); // 最大 Chunk
三、静态初始化块(static 块)
这是整个类最重要的部分之一,负责计算默认配置。
3.1 Page 大小计算
// 1. 获取 Page 大小(可通过系统属性配置)
int defaultPageSize = SystemPropertyUtil.getInt("io.netty.allocator.pageSize", 8192);
// 2. 验证 Page 大小
try {
validateAndCalculatePageShifts(defaultPageSize);
} catch (Throwable t) {
pageSizeFallbackCause = t;
defaultPageSize = 8192; // 验证失败,使用默认值
}
DEFAULT_PAGE_SIZE = defaultPageSize;
验证逻辑:
private static int validateAndCalculatePageShifts(int pageSize) {
// 1. 必须 >= 4096
if (pageSize < MIN_PAGE_SIZE) {
throw new IllegalArgumentException("pageSize: " + pageSize + " (expected: " + MIN_PAGE_SIZE + ")");
}
// 2. 必须是 2 的幂次方
if ((pageSize & pageSize - 1) != 0) {
throw new IllegalArgumentException("pageSize: " + pageSize + " (expected: power of 2)");
}
// 3. 计算 pageShifts(用于位运算优化)
// 例如:8192 = 2^13,返回 13
return Integer.SIZE - 1 - Integer.numberOfLeadingZeros(pageSize);
}
3.2 MaxOrder 计算
// 1. 获取 MaxOrder(可通过系统属性配置)
int defaultMaxOrder = SystemPropertyUtil.getInt("io.netty.allocator.maxOrder", 11);
// 2. 验证 MaxOrder
try {
validateAndCalculateChunkSize(DEFAULT_PAGE_SIZE, defaultMaxOrder);
} catch (Throwable t) {
maxOrderFallbackCause = t;
defaultMaxOrder = 11; // 验证失败,使用默认值
}
DEFAULT_MAX_ORDER = defaultMaxOrder;
验证逻辑:
private static int validateAndCalculateChunkSize(int pageSize, int maxOrder) {
// 1. maxOrder 必须 <= 14
if (maxOrder > 14) {
throw new IllegalArgumentException("maxOrder: " + maxOrder + " (expected: 0-14)");
}
// 2. 计算 ChunkSize,确保不溢出
int chunkSize = pageSize;
for (int i = maxOrder; i > 0; i--) {
if (chunkSize > MAX_CHUNK_SIZE / 2) {
throw new IllegalArgumentException(String.format(
"pageSize (%d) << maxOrder (%d) must not exceed %d",
pageSize, maxOrder, MAX_CHUNK_SIZE));
}
chunkSize <<= 1; // chunkSize *= 2
}
return chunkSize;
}
计算示例:
pageSize = 8192 (8KB)
maxOrder = 11
chunkSize = 8192 << 11
= 8192 * 2^11
= 8192 * 2048
= 16,777,216 字节
= 16 MB
3.3 Arena 数量计算(重点)
final Runtime runtime = Runtime.getRuntime();
// 1. 默认最小 Arena 数量 = CPU 核心数 * 2
final int defaultMinNumArena = NettyRuntime.availableProcessors() * 2;
// 2. 计算 ChunkSize
final int defaultChunkSize = DEFAULT_PAGE_SIZE << DEFAULT_MAX_ORDER; // 16MB
// 3. 计算堆内存 Arena 数量
DEFAULT_NUM_HEAP_ARENA = Math.max(0,
SystemPropertyUtil.getInt(
"io.netty.allocator.numHeapArenas",
(int) Math.min(
defaultMinNumArena,
runtime.maxMemory() / defaultChunkSize / 2 / 3)));
// 4. 计算直接内存 Arena 数量
DEFAULT_NUM_DIRECT_ARENA = Math.max(0,
SystemPropertyUtil.getInt(
"io.netty.allocator.numDirectArenas",
(int) Math.min(
defaultMinNumArena,
PlatformDependent.maxDirectMemory() / defaultChunkSize / 2 / 3)));
计算逻辑详解:
假设:
- CPU 核心数 = 8
- 堆内存 = 4GB = 4096MB
- ChunkSize = 16MB
计算过程:
defaultMinNumArena = 8 * 2 = 16
方案1:基于 CPU 核心数
numArena = 16
方案2:基于可用内存
numArena = 4096MB / 16MB / 2 / 3
= 256 / 2 / 3
= 42.67
= 42
最终:
DEFAULT_NUM_HEAP_ARENA = min(16, 42) = 16
为什么除以 2 / 3?
- 除以 2:假设每个 Arena 平均有 2 个 Chunk
- 除以 3:内存池不应该占用超过 50% 的可用内存
- 保守估计,避免内存不足
3.4 ThreadCache 配置
// Tiny 缓存大小(< 512B)
DEFAULT_TINY_CACHE_SIZE = SystemPropertyUtil.getInt(
"io.netty.allocator.tinyCacheSize", 512);
// Small 缓存大小(512B ~ 8KB)
DEFAULT_SMALL_CACHE_SIZE = SystemPropertyUtil.getInt(
"io.netty.allocator.smallCacheSize", 256);
// Normal 缓存大小(8KB ~ 16MB)
DEFAULT_NORMAL_CACHE_SIZE = SystemPropertyUtil.getInt(
"io.netty.allocator.normalCacheSize", 64);
// 最大缓存容量(32KB)
DEFAULT_MAX_CACHED_BUFFER_CAPACITY = SystemPropertyUtil.getInt(
"io.netty.allocator.maxCachedBufferCapacity", 32 * 1024);
// 缓存清理间隔(每分配 8192 次触发一次清理)
DEFAULT_CACHE_TRIM_INTERVAL = SystemPropertyUtil.getInt(
"io.netty.allocator.cacheTrimInterval", 8192);
// 是否所有线程使用缓存
DEFAULT_USE_CACHE_FOR_ALL_THREADS = SystemPropertyUtil.getBoolean(
"io.netty.allocator.useCacheForAllThreads", true);
为什么 Tiny 缓存最大?
Tiny (512 个) > Small (256 个) > Normal (64 个)
原因:
1. Tiny 对象(< 512B)最常用
- 协议头、小消息、控制信息
- 分配频率最高
2. Small 对象(512B ~ 8KB)次之
- 大部分网络数据包
- 分配频率中等
3. Normal 对象(8KB ~ 16MB)最少
- 大文件、批量数据
- 分配频率最低
四、实例变量
// 默认实例(单例)
public static final PooledByteBufAllocator DEFAULT =
new PooledByteBufAllocator(PlatformDependent.directBufferPreferred());
// Arena 数组
private final PoolArena<byte[]>[] heapArenas; // 堆内存 Arena
private final PoolArena<ByteBuffer>[] directArenas; // 直接内存 Arena
// ThreadCache 配置
private final int tinyCacheSize;
private final int smallCacheSize;
private final int normalCacheSize;
// 监控指标
private final List<PoolArenaMetric> heapArenaMetrics;
private final List<PoolArenaMetric> directArenaMetrics;
// 线程本地缓存管理器
private final PoolThreadLocalCache threadCache;
// Chunk 大小
private final int chunkSize;
// 分配器指标
private final PooledByteBufAllocatorMetric metric;
五、构造函数
5.1 构造函数链
// 1. 无参构造
public PooledByteBufAllocator() {
this(false); // 不优先使用直接内存
}
// 2. 指定 preferDirect
public PooledByteBufAllocator(boolean preferDirect) {
this(preferDirect, DEFAULT_NUM_HEAP_ARENA, DEFAULT_NUM_DIRECT_ARENA,
DEFAULT_PAGE_SIZE, DEFAULT_MAX_ORDER);
}
// 3. 自定义 Arena 数量
public PooledByteBufAllocator(int nHeapArena, int nDirectArena,
int pageSize, int maxOrder) {
this(false, nHeapArena, nDirectArena, pageSize, maxOrder);
}
// 4. 完整构造(最终调用)
public PooledByteBufAllocator(boolean preferDirect, int nHeapArena,
int nDirectArena, int pageSize, int maxOrder,
int tinyCacheSize, int smallCacheSize,
int normalCacheSize,
boolean useCacheForAllThreads,
int directMemoryCacheAlignment) {
// 实际的初始化逻辑
}
5.2 核心构造逻辑
public PooledByteBufAllocator(boolean preferDirect, int nHeapArena,
int nDirectArena, int pageSize, int maxOrder,
int tinyCacheSize, int smallCacheSize,
int normalCacheSize,
boolean useCacheForAllThreads,
int directMemoryCacheAlignment) {
// 1. 调用父类构造
super(preferDirect);
// 2. 创建 ThreadCache 管理器
threadCache = new PoolThreadLocalCache(useCacheForAllThreads);
// 3. 保存缓存配置
this.tinyCacheSize = tinyCacheSize;
this.smallCacheSize = smallCacheSize;
this.normalCacheSize = normalCacheSize;
// 4. 计算并验证 ChunkSize
chunkSize = validateAndCalculateChunkSize(pageSize, maxOrder);
// 5. 验证参数
checkPositiveOrZero(nHeapArena, "nHeapArena");
checkPositiveOrZero(nDirectArena, "nDirectArena");
checkPositiveOrZero(directMemoryCacheAlignment, "directMemoryCacheAlignment");
// 6. 计算 pageShifts
int pageShifts = validateAndCalculatePageShifts(pageSize);
// 7. 创建堆内存 Arena 数组
if (nHeapArena > 0) {
heapArenas = newArenaArray(nHeapArena);
List<PoolArenaMetric> metrics = new ArrayList<>(heapArenas.length);
for (int i = 0; i < heapArenas.length; i++) {
PoolArena.HeapArena arena = new PoolArena.HeapArena(
this, pageSize, maxOrder, pageShifts, chunkSize,
directMemoryCacheAlignment);
heapArenas[i] = arena;
metrics.add(arena);
}
heapArenaMetrics = Collections.unmodifiableList(metrics);
} else {
heapArenas = null;
heapArenaMetrics = Collections.emptyList();
}
// 8. 创建直接内存 Arena 数组
if (nDirectArena > 0) {
directArenas = newArenaArray(nDirectArena);
List<PoolArenaMetric> metrics = new ArrayList<>(directArenas.length);
for (int i = 0; i < directArenas.length; i++) {
PoolArena.DirectArena arena = new PoolArena.DirectArena(
this, pageSize, maxOrder, pageShifts, chunkSize,
directMemoryCacheAlignment);
directArenas[i] = arena;
metrics.add(arena);
}
directArenaMetrics = Collections.unmodifiableList(metrics);
} else {
directArenas = null;
directArenaMetrics = Collections.emptyList();
}
// 9. 创建监控指标
metric = new PooledByteBufAllocatorMetric(this);
}
初始化流程图:
构造函数
↓
1. 创建 PoolThreadLocalCache
↓
2. 创建 HeapArena 数组
├─ HeapArena[0]
├─ HeapArena[1]
└─ ...
↓
3. 创建 DirectArena 数组
├─ DirectArena[0]
├─ DirectArena[1]
└─ ...
↓
4. 创建监控指标
六、核心方法
6.1 分配堆内存
@Override
protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
// 1. 获取当前线程的 ThreadCache
PoolThreadCache cache = threadCache.get();
PoolArena<byte[]> heapArena = cache.heapArena;
final ByteBuf buf;
if (heapArena != null) {
// 2. 从 Arena 分配(会先尝试 ThreadCache)
buf = heapArena.allocate(cache, initialCapacity, maxCapacity);
} else {
// 3. 没有 Arena,使用非池化分配
buf = PlatformDependent.hasUnsafe() ?
new UnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity) :
new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
}
// 4. 包装成泄漏检测的 ByteBuf
return toLeakAwareBuffer(buf);
}
6.2 分配直接内存
@Override
protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
// 1. 获取当前线程的 ThreadCache
PoolThreadCache cache = threadCache.get();
PoolArena<ByteBuffer> directArena = cache.directArena;
final ByteBuf buf;
if (directArena != null) {
// 2. 从 Arena 分配(会先尝试 ThreadCache)
buf = directArena.allocate(cache, initialCapacity, maxCapacity);
} else {
// 3. 没有 Arena,使用非池化分配
buf = PlatformDependent.hasUnsafe() ?
UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity) :
new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
}
// 4. 包装成泄漏检测的 ByteBuf
return toLeakAwareBuffer(buf);
}
分配流程:
用户调用:allocator.buffer(1024)
↓
newHeapBuffer() 或 newDirectBuffer()
↓
1. threadCache.get() → 获取 PoolThreadCache
├─ 第一次访问:调用 initialValue() 创建
└─ 后续访问:直接返回
↓
2. cache.heapArena 或 cache.directArena
↓
3. arena.allocate(cache, initialCapacity, maxCapacity)
├─ 先尝试从 ThreadCache 分配(快)
└─ 未命中再从 Arena 分配(慢)
↓
4. toLeakAwareBuffer(buf) → 包装泄漏检测
七、PoolThreadLocalCache 内部类(重点)
final class PoolThreadLocalCache extends FastThreadLocal<PoolThreadCache> {
private final boolean useCacheForAllThreads;
PoolThreadLocalCache(boolean useCacheForAllThreads) {
this.useCacheForAllThreads = useCacheForAllThreads;
}
@Override
protected synchronized PoolThreadCache initialValue() {
// 1. 选择负载最小的 Arena
final PoolArena<byte[]> heapArena = leastUsedArena(heapArenas);
final PoolArena<ByteBuffer> directArena = leastUsedArena(directArenas);
final Thread current = Thread.currentThread();
// 2. 判断是否使用缓存
if (useCacheForAllThreads || current instanceof FastThreadLocalThread) {
// 创建带缓存的 PoolThreadCache
final PoolThreadCache cache = new PoolThreadCache(
heapArena, directArena,
tinyCacheSize, smallCacheSize, normalCacheSize,
DEFAULT_MAX_CACHED_BUFFER_CAPACITY,
DEFAULT_CACHE_TRIM_INTERVAL);
// 3. 定时清理缓存
if (DEFAULT_CACHE_TRIM_INTERVAL_MILLIS > 0) {
final EventExecutor executor = ThreadExecutorMap.currentExecutor();
if (executor != null) {
executor.scheduleAtFixedRate(
trimTask,
DEFAULT_CACHE_TRIM_INTERVAL_MILLIS,
DEFAULT_CACHE_TRIM_INTERVAL_MILLIS,
TimeUnit.MILLISECONDS);
}
}
return cache;
}
// 4. 不使用缓存(缓存大小为 0)
return new PoolThreadCache(heapArena, directArena, 0, 0, 0, 0, 0);
}
@Override
protected void onRemoval(PoolThreadCache threadCache) {
// 线程结束时释放缓存
threadCache.free(false);
}
// 选择负载最小的 Arena
private <T> PoolArena<T> leastUsedArena(PoolArena<T>[] arenas) {
if (arenas == null || arenas.length == 0) {
return null;
}
PoolArena<T> minArena = arenas[0];
for (int i = 1; i < arenas.length; i++) {
PoolArena<T> arena = arenas[i];
if (arena.numThreadCaches.get() < minArena.numThreadCaches.get()) {
minArena = arena;
}
}
return minArena;
}
}
负载均衡逻辑:
假设有 4 个 Arena:
Arena[0]: 绑定了 5 个线程
Arena[1]: 绑定了 3 个线程 ← 最少
Arena[2]: 绑定了 4 个线程
Arena[3]: 绑定了 6 个线程
新线程创建 ThreadCache 时:
选择 Arena[1](负载最小)
八、监控和统计方法
// 获取监控指标
@Override
public PooledByteBufAllocatorMetric metric() {
return metric;
}
// 清理当前线程的缓存
public boolean trimCurrentThreadCache() {
PoolThreadCache cache = threadCache.getIfExists();
if (cache != null) {
cache.trim();
return true;
}
return false;
}
// 打印统计信息
public String dumpStats() {
int heapArenasLen = heapArenas == null ? 0 : heapArenas.length;
StringBuilder buf = new StringBuilder(512)
.append(heapArenasLen)
.append(" heap arena(s):")
.append(StringUtil.NEWLINE);
if (heapArenasLen > 0) {
for (PoolArena<byte[]> a: heapArenas) {
buf.append(a);
}
}
int directArenasLen = directArenas == null ? 0 : directArenas.length;
buf.append(directArenasLen)
.append(" direct arena(s):")
.append(StringUtil.NEWLINE);
if (directArenasLen > 0) {
for (PoolArena<ByteBuffer> a: directArenas) {
buf.append(a);
}
}
return buf.toString();
}
九、核心要点总结
9.1 职责
- 管理 Arena:创建和管理多个 Arena,减少线程竞争
- 管理 ThreadCache:为每个线程创建本地缓存,提升性能
- 提供分配接口:统一的内存分配入口
- 监控统计:提供内存使用情况的监控指标
9.2 关键设计
-
多 Arena 设计:
- 默认 CPU 核心数 * 2
- 减少线程竞争
- 负载均衡
-
ThreadCache 设计:
- 线程本地缓存
- 无锁分配
- 定时清理
232



被折叠的 条评论
为什么被折叠?



