Netty出现io.netty.util.internal.OutOfDirectMemoryError的解决咨询
解决Netty的OutOfDirectMemoryError问题
问题原因
你遇到的io.netty.util.internal.OutOfDirectMemoryError是Netty直接内存耗尽导致的:
- 当前已用直接内存134MB(134217728字节),刚好达到上限阈值
- 错误发生在SSL解码阶段,说明高并发/长连接场景下,直接内存的分配、回收出现瓶颈,间歇性出现大概率是内存泄漏或者流量峰值超出限制
解决方案
1. 临时提升直接内存上限
这是最快的临时解决办法,直接调整Netty的直接内存阈值:
- 在JVM启动参数中添加:
这里设置为256MB,可根据服务器内存情况调整(比如512MB或1GB)。注意Netty的这个参数优先级高于JVM的-Dio.netty.maxDirectMemory=268435456-XX:MaxDirectMemorySize。
2. 排查并修复内存泄漏
间歇性错误基本是内存泄漏导致的,开启Netty的泄漏检测定位问题:
- 添加启动参数开启高级泄漏检测:
检测到ByteBuf未正确释放时,会打印完整调用栈,帮你找到未释放内存的代码位置。-Dio.netty.leakDetection.level=advanced - 新手务必注意:所有手动分配的ByteBuf必须调用
release()释放,或者用try-with-resources自动释放(Netty 4.1及以上支持):try (ByteBuf buf = ctx.alloc().directBuffer()) { // 业务逻辑处理buf } - 检查SSL连接关闭时的资源释放:确保
SslHandler在channelInactive事件中正确清理会话缓存和相关内存。
3. 优化ByteBuf分配策略
- 改用堆内存测试:如果暂时不想处理直接内存问题,可临时改用堆内存分配器(适合低并发场景,高并发下性能会下降):
// 初始化客户端/服务器时设置 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT); - 调整池化参数:使用默认
PooledByteBufAllocator时,可调整池大小和缓存策略,减少内存碎片化:PooledByteBufAllocator allocator = new PooledByteBufAllocator(true, 4, 4, 1024, 10); bootstrap.option(ChannelOption.ALLOCATOR, allocator);
4. 优化SSL配置减少内存消耗
SSL握手和会话管理是内存消耗大户,优化配置可降低内存压力:
- 开启SSL会话复用,减少重复握手的内存开销:
SslContext sslContext = SslContextBuilder.forServer(new File("cert.pem"), new File("key.pem")) .sessionCacheSize(1000) // 缓存1000个会话 .sessionTimeout(300) // 会话超时300秒 .build(); - 尽量使用长连接,减少频繁创建/销毁SSL连接带来的内存波动。
内容的提问来源于stack exchange,提问作者joe1903
相关产品推荐
相关产品推荐

