服务在启动时总会出现这样的日志



但只会出现一次,而且报告内存泄漏的线程也不固定,由报告线程栈来看,不由得让人产生这样的疑问 “难道所有使用了netty的框架都有内存泄漏?”
由于对netty不了解, 那时的我是这样认为的(2020年前我其实没写过什么Java代码,更别提Netty啦)
-
内存泄漏日志只出现一次,那应该就只有一次内存泄漏,没什么影响
-
已经发现了内存泄漏,框架应该会把泄漏的内存回收掉,没什么影响
但事实确不是这样,随着服务的长时间运行最终会迎来堆外内存OOM(如果服务存在堆外内存泄漏,但一时半会又无法定位解决,还是不要设置-XX:MaxDirectMemorySize为好,让它触发oom killer挂掉重启或者捕获了OutOfMemory后异常退出服务触发重启,不然服务还是会正常接收请求,但返回数据为空,影响服务质量)


事实是什么?
为了看清事实,我们需要先了解一点netty检测内存泄漏的原理
对于使用netty的PooledByteBufAllocator分配出去的ByteBuf对象(下文皆指堆外内存),netty都会用一个DefaultResourceLeak的弱引用对象去跟踪,当ByteBuf对象被垃圾回收,DefaultResourceLeak对象就会被放到与之关联的引用队列中(DefaultResourceLeak对象创建时指定的队列),当有业务线程调用newDirectBuffer分配内存时就会调用reportLeak触发内存泄漏检查(这就是为什么内存泄漏时,报告线程不固定的原因),而且每个泄漏点只会报告一次(netty会把每次已经报告的泄漏点记录下来)




最低0.47元/天 解锁文章
10万+

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



