最近用Netty框架开发网络应用时,出现几个异常报错,仔细一看是内存泄漏了,提示ByteBuf对象在回收之前没有调用ByteBuf.release()

ERROR io.netty.util.ResourceLeakDetector - LEAK: ByteBuf.release() was not called before it's garbage-collected

出现这个问题是因为程序中生成了池化的ByteBuf(PooledByteBuf)。PooledByteBuf的内存空间是从内存池中分配的,并且内部维持了一个计数器,用来记录引用次数。PooledByteBuf在使用完之后要手动调用release()函数,该函数会减小引用次数,减小到0时就会将内存归还在内存池中。如果不调用release()函数,JVM不知道引用计数的存在,释放该对象时,可能还有其他引用在使用该内存空间,该内存空间也无法归还到内存池中,从而导致内存泄漏。

关于ByteBuf内存泄漏更详细的资料请移步Netty中ByteBuf内存泄露及释放解析 

解决方法就是找到报错的位置,找到生成的ByteBuf对象,在使用完之后调用对象的relesse()函数或者加上一句ReferenceCountUtil.release(msg)。如下面我出现的报错

2020-06-12 17:04:41.242 [nioEventLoopGroup-2-1] ERROR io.netty.util.ResourceLeakDetector - LEAK: ByteBuf.release() was not called before it's garbage-collected. See https://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records: 
Created at:
    io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:363)
    io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:187)
    io.netty.buffer.AbstractByteBufAllocator.buffer(AbstractByteBufAllocator.java:123)
    io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:872)
    com.spring.netty.twg.service.TwgMessageDecoder.formatDecoder(TwgMessageDecoder.java:176)
    com.spring.netty.twg.service.TwgMessageDecoder.getMessageBody(TwgMessageDecoder.java:90)
    com.spring.netty.twg.service.TwgMessageDecoder.decode(TwgMessageDecoder.java:76)
    io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:332)
    io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:501)

在formatDecoder函数中,我调用readBytes()函数生成新ByteBuf对象byteBufChar。

在使用结束时,调用byteBufChar的release()函数  byteBufChar.release();

2020-06-12 17:04:45.460 [nioEventLoopGroup-2-1] ERROR io.netty.util.ResourceLeakDetector - LEAK: ByteBuf.release() was not called before it's garbage-collected. See https://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records: 
Created at:
    io.netty.buffer.SimpleLeakAwareByteBuf.unwrappedDerived(SimpleLeakAwareByteBuf.java:143)
    io.netty.buffer.SimpleLeakAwareByteBuf.retainedSlice(SimpleLeakAwareByteBuf.java:57)
    io.netty.handler.codec.LengthFieldBasedFrameDecoder.extractFrame(LengthFieldBasedFrameDecoder.java:498)
    io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:437)
    com.spring.netty.twg.service.TwgMessageDecoder.decode(TwgMessageDecoder.java:31)
    io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:332)

在decode函数中,我调用了父类的decode()函数,生成新BytyBuf对象in,

在使用结束时,调用工具类,帮助回收in对象  ReferenceCountUtil.release(in)或者直接调用release()

posted on 2020-06-14 00:18  zhaoshizi  阅读(11725)  评论(0编辑  收藏  举报