第五天:深度解密 Netty ByteBuf:高性能 IO 的基石

Netty ByteBuf:直接内存 vs 堆内存

Netty的ByteBuf分配和Java NIOByteBuffer类似

复制代码
// 堆内存
ByteBuf heapBuf = allocator.heapBuffer(10);

// 直接内存
ByteBuf directBuf = allocator.directBuffer(10);

|---------|-------------|----------------|
| 对比项 | 堆内存 ByteBuf | 直接内存 ByteBuf |
| 内存位置 | JVM 堆 | JVM 堆外 |
| GC 管理 | 是 | 否 |
| IO 性能 | 慢(多一次拷贝) | 快(少一次拷贝) |
| 创建成本 | 低 | 高 |
| 是否需手动释放 | 否 | 是(release) |

Direct ByteBuf 提高 IO 性能、降低 GC 压力,但创建成本高且需要手动释放;Heap ByteBuf 管理简单,但 IO 性能差。

按你刚才的要求,继续**极限精简,只保留"有用信息"**👇


Netty ByteBuf:池化 vs 非池化(精简版)

复用 ByteBuf,避免频繁创建 / 销毁的事件耗费

2️⃣ 核心差异

|------------|-------------------|--------|
| 对比 | 非池化 | 池化 |
| ByteBuf 获取 | 每次 new | 从池中复用 |
| 直接内存成本 | 高(频繁 malloc/free) | 低 |
| GC / 内存压力 | 大 | 小 |
| 并发场景 | 不友好 | 友好 |


3️⃣ 启用方式

复制代码
-Dio.netty.allocator.type=pooled   # 池化
-Dio.netty.allocator.type=unpooled # 非池化

4️⃣ 默认策略(记结论)

  • Netty 4.1+ :非 Android 默认 池化
  • Android:默认非池化
  • 4.1 之前:默认非池化(池化不成熟)

池化通过复用 ByteBuf 降低直接内存分配成本和 GC 压力,是 Netty 在高并发 IO 场景下的关键优化手段。

组成

ByteBuf由四部分组成

  1. 读指针(readerIndex):标记当前可读数据的起始位置。
  2. 写指针(writerIndex):标记当前可写数据的起始位置。
  3. 容量(capacity):当前 ByteBuf 实际占用的内存大小。
  4. 最大容量(maxCapacity):ByteBuf 可扩容到的最大内存限制。

相比于ByttBuffer,不用来回切换读写模式更方便,且支持动态扩容

整数大端写入端:更符合读书习惯

整数小端写入: CPU 从低位到高位的运算顺序,内存访问更连续。

ByteBuf扩容规则:

  1. 如果写入字节小于512,则容量下一次为16的整数倍。
  2. 如果写入字节大于512,则容量下一次为2^n
  3. 扩容后不能超过max capacity

内存释放

核心机制:引用计数 (Reference Counting)

Netty 的 ByteBuf 实现了 ReferenceCounted 接口。

  • 初始状态: 创建一个新的 ByteBuf 时,引用计数 refCnt1
  • Retain (保留): 调用 buf.retain(),引用计数 +1。表示有新的地方在使用它。
  • Release (释放): 调用 buf.release(),引用计数 -1
  • 回收: 当引用计数变为 0 时,Netty 会将该内存块归还给内存池(Pooled)或直接销毁(Unpooled)。

警告: 如果引用计数未归零,GC 无法回收堆外内存(Direct Memory),将直接导致 内存泄漏 (Memory Leak) 。如果引用计数归零后继续访问即使ByteBuf对象还在,但是底层内存会被回收,会抛出 IllegalReferenceCountException

释放时机:而在netty中一个基本原则:"谁最后使用(消费)了数据,谁就负责释放。"

Slice;切片

【零拷贝】的体现之一,对原始 ByteBuf 进行切片成多个 ByteBuf, 切片后的 ByteBuf 并没有发生内存复制,还是使用原始 ByteBuf 的内存,切片后的 ByteBuf 维护独立的 read, write 指针

逻辑上对ByteBuf进行切分,其实物理内存还是同一块

ByteBuf.slice(index1,index2)

index1:起始位置

index2:切片长度

切片共享原始内存,容量固定,原 ByteBuf 一旦释放,切片就不可用了;

写入超界会抛异常,安全使用需要正确管理引用计数。

duplicate

【零拷贝】的体现之一,就好比截取了原始 ByteBuf 所有内容,并且没有 max capacity 的限制,也是与原始ByteBuf 使用同一块底层内存,只是读写指针是独立的

零拷贝相反Copy

会将底层内存数据进行深拷贝,无论读写,都与原始ByteBuf无关

Composite

CompositeByteBuf

把多个 ByteBuf 逻辑上拼接成一个连续缓冲区

unPooled

unpooled 是 Netty 提供的一个 工具类,用来创建 非池化(unpooled)的 ByteBuf,区别于 Netty 的 池化 ByteBuf(PooledByteBuf)。它的核心作用和特点可以总结如下:

相关推荐
小弥儿1 小时前
开源 VoiceStudio,声音克隆|配音|有声书一站式本地完成
学习·开源·github
2601_962071574 小时前
【Java报错已解决】org.springframework.beans.factory.BeanCreationException
java·开发语言
zww89491115 小时前
酒馆预约系统开发实战:从需求分析到上线全流程指南
java·eclipse
DM今天肝到几点?7 小时前
AI 安全进入「攻防同频」:Gemini 3.8 Flash Cyber 上线、Astra 触及关键级、HiddenLayer 融资 1 亿美元
网络·人工智能·深度学习·安全·语言模型·开源·知识图谱
冬奇Lab7 小时前
一天一个开源项目(第207篇):AirLLM - 单卡 4GB 跑 70B 大模型
人工智能·开源
zww89491118 小时前
匿名树洞系统开发实战:从需求分析到部署指南
java·eclipse
行百里er8 小时前
Gateway 上别硬塞 MVC:DeferredImportSelector 看菜下锅
spring boot·后端·开源
十六年开源服务商9 小时前
2026年WordPress页面构建器终极选型指南
开源
黑马程序员毕设9 小时前
基于Java的医院药品管理系统的优化设计与实现
java·开发语言·spring boot·小程序·架构·课程设计·毕设
木井巳9 小时前
【BFS/DFS 解决 FloodFill 算法】太平洋大西洋水流问题
java·算法·leetcode·深度优先·广度优先·宽度优先·推荐算法