上一篇【第39篇】Netty内存泄漏检测机制源码解析——守护ByteBuf的“生死账本“
下一篇【第41篇】Netty开发HTTP服务——打造轻量级Web服务器(明日更新,敬请期待)
一、内存管理架构
PooledByteBufAllocator ├── heapArenas[N] (堆内Arena数组) └── directArenas[N] (直接内存Arena数组) │ ├── PoolChunkList[6] (按使用率分6级) │ └── PoolChunk (16MB) │ ├── PoolSubpage[2048] (8KB/页) │ │ └── bitmap (按规格切割: 16B/32B/...) │ └── memoryMap (完全二叉树,buddy算法) │ └── PoolThreadCache (线程缓存) ├── tinySubPageCaches[32] (<512B) ├── smallSubPageCaches[4] (512B~8KB) └── normalCaches[3] (8KB~16MB)二、PoolChunk:buddy算法分配≥8KB
// Chunk = 16MB = 2048 × 8KB pages// 使用完全二叉树管理,深度11层// memoryMap: 4096个节点的数组// allocateRun(normCapacity):分配≥8KB的内存longallocateRun(intnormCapacity){intd=maxOrder-log2(normCapacity/pageSize);// 计算深度intid=allocateNode(d);// 在二叉树中查找空闲节点updateParentsAlloc(id);// 更新父节点的分配状态returnid;}// memoryMap[id] = depth_of_id 表示空闲// memoryMap[id] = 不可用值(12) 表示已分配intallocateNode(intd){intid=1;// 从根节点开始for(inti=1;i<=d;i++){intleft=id<<1;intright=left|1;if(memoryMap[left]<=d){id=left;// 左子树有空闲}elseif(memoryMap[right]<=d){id=right;// 右子树有空闲}else{return-1;// 无可用空间}}memoryMap[id]=12;// 标记为已分配returnid;}三、PoolSubpage:slab分配<8KB
// 一页8KB,切成n个等大小块// 例如:请求1KB → 切成8块,每块1KB// 使用bitmap管理分配longallocate(){intbitmapIdx=getNextAvail();// bitmap找空闲位intq=bitmapIdx>>>6;// bitmap中的第几个longintr=bitmapIdx&63;// long中的第几个bitbitmap[q]|=1L<<r;// 标记为已分配returntoHandle(bitmapIdx);}四、分配流程
请求分配1024字节 ↓ 优先查 PoolThreadCache(线程缓存) ↓ 未命中 查 PoolArena ↓ < 8KB? → PoolSubpage (slab分配) ↓ ≥ 8KB? → PoolChunk (buddy分配) ↓ 无可用Chunk 创建新Chunk → 分配五、内存池回收
// Chunk使用率降到0% → 从活跃列表移除 → 可能被回收// 使用率变化在 q000→q025→q050→q075→q100 之间迁移// 6级ChunkList:// qInit → q000 → q025 → q050 → q075 → q100// (使用率0-25%) (25-50%) (50-75%) (75-100%)六、总结
| 组件 | 职责 | 大小范围 |
|---|---|---|
| PoolThreadCache | 线程级缓存 | 多种规格 |
| PoolSubpage | slab小对象分配 | < 8KB |
| PoolChunk | buddy大对象分配 | 8KB ~ 16MB |
| PoolArena | 管理ChunkList | 整体协调 |
上一篇【第39篇】Netty内存泄漏检测机制源码解析——守护ByteBuf的“生死账本“
下一篇【第41篇】Netty开发HTTP服务——打造轻量级Web服务器(明日更新,敬请期待)