随笔分类
怎么理解 Netty中内存资源泄漏?
什么是资源?线程、内存、连接、文件皆是资源!
对于服务器而言,我们显然更关注前两者
介于资源创建的昂贵,引用了一些相关的池化技术,如线程池、连接池、对象池、内存池等等,池化技术的引入,实实在在地提升了程序的性能,但相应地也带来了一些问题,so,我们需要来对其进行处理
Netty中池化内存同样如此!使用不当,仍然可能会带来内存泄漏的隐患!
经过前面分析,我们知道,当我们向程序去申请内存时,内存的管理是经由内存池的
当我们去申请内存时,首先会到对象池中去获取一个空闲的 ByteBuf,此时的 ByteBuf尚未被分配内存信息,即其相当于一个容器的存在,之后我们会到内存池中去为其 "赋能" -- 这块详细可去看对内存池申请内存的解读篇
我们返回业务使用的是 ByteBuf,其实际上是去实现了 ReferenceCounted操作,因此在业务使用时,我们可以通过对其进行 retain()、release()操作,实现内存对象的申请与归还释放 (默认申请时,其 cnt = 1)
假设一种场景,当上层业务从内存池中获取响应内存后,做了些数据处理,然后将数据写出到 socket写缓冲区中
经过前面对出站缓冲区的分析,我们知道数据在真正写出到 Socket写缓冲区中时,首先会去经过一个出站缓冲区,而出站缓冲区会去响应出站事件 (flush操作),会去找到对应的 ByteBuf,将其中的信息刷新到 Socket写缓冲区中去,然后将该 ByteBuf引用计数减一,当判断出 cnt等于 0时,会去进行释放内存的操作,实际上就是去将容器归还到对象池,然后将这部分内存归还到内存池 (先本地缓存延迟释放...),这实际上就形成了一个闭环的操作,这是正常逻辑,未出现内存资源泄漏的 case
而异常的逻辑是什么?业务层面对 ByteBuf进行了多次 ratain()操作,然后再经过与上面相同的逻辑,最终在执行 release()是发现,其 cnt != 0,由于其引用计数不为 0,并且业务不会再去使用它,而这部分内存得不到释放,在内存池逻辑层面这块内存还是处于不可占用分配状态
那么,当这种 case多了后,Netty中可分配的内存越来越少了以后,对应业务不会去再去使用对应内存,但仍会不断向池子中申请内存,这不就对应的便是 "内存泄漏"么?
这便是 Netty中出现内存泄漏的 case!so,Netty也对该 case进行了追踪,给出了一个解决方案!下一篇,将进行解读!