Netty-内存泄漏检测

内存检测原理使用的是PhantomReference技术,通过判断ByteBuf的refCount是否为0,判断是否存在内存泄漏。

检测原理

无论是池化的ByteBuf还是非池化的ByteBuf,BuyeBuf(不一定是该对象)对象在被gc回收之后,通过判断refCount是否为0来判断是否发生了内存泄漏。

netty支持下面四种级别,使用-Dio.netty.leakDetectionLevel=advanced可以调节等级。

  • 禁用(DISABLED) - 完全禁止泄露检测,省点消耗。
  • 简单(SIMPLE) - 默认等级,告诉我们取样的1%的ByteBuf是否发生了泄露,但总共一次只打印一次,看不到就没有了。
  • 高级(ADVANCED) - 告诉我们取样的1%的ByteBuf发生泄露的地方。每种类型的泄漏(创建的地方与访问路径一致)只打印一次。对性能有影响。
  • 偏执(PARANOID) - 跟高级选项类似,但此选项检测所有ByteBuf,而不仅仅是取样的那1%。对性能有绝大的影响。

SIMPLE级别113才采样一个,但是每次新建一个buffer都会执行一次reportLeak进行内存泄漏检测。

检测出内存泄漏就说明有问题

对于非池化的ByteBuf不会有问题,但是池化的ByteBuf有问题。

  1. 因为非池化的ByteBuf即使refCount没减为0,但是gc机制也会回收掉对应内存,所以不会造成大问题。但是如果程序及时释放不使用的内存肯定更好,以便该内存能被及时的会回收掉。
  2. 虽然ByteBuf可以被gc回收,但是ByteBuf内部引用的数组内存还是被池数据结构引用不能被释放,造成内存不能释放给到池子,最终造成池子里无内存可分配。

如何释放ByteBuf

ReferenceCountUtil.release(msg);

一个内存泄漏案例

设备上行的消息大小超过限制后就直接关闭了channel,而没有释放内存。
OOM信息?内存检测信息?


image.png

程序一定要显示的释放内存

以非池化的BuyeBuf举例。对于堆内内存,netty会把数组对象置为空使内存可以快速的被GC会收掉。对于直接内存,ntty会直接通过cleaner释放掉内存,而不用等GC机制释放掉(GC释放直接内存不是很靠谱)。

参考

Netty之有效规避内存泄漏

你可能感兴趣的:(Netty-内存泄漏检测)