昨天解决了队列过大导致内存溢出的一个问题,今天起床再看下程序,发现程序其他线程均停止了,只有一个monitor线程再不断打出监控数据。可以看到队列的问题不存在了!因为队列根本没数据!!但是其他线程还是hang住了!
用jmap 打印出堆栈信息发行当前内存使用也是正常的,没有被占完。这就百思不得其解了。后面猛然想到,偶然在哪看过一篇文章netty好像有一步需要手动释放内存的。= = 去搜索了下果然...
netty的ByteBuff如果是自己分配的,没有提交给netty write的需要手动释放!
ReferenceCountUtil.release(byteBuf);
netty设计者早就考虑到了这个坑所以会抽样一部分的ByteBuff 并且打出警告日志
提醒你某个地方的ByteBuff忘记释放了。但是这个报错还是只打一次。还是得加了这个
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
的情况下才会打出堆栈信息 - -。 所以这个错误就被埋葬在茫茫多的调试信息里面了。
自己申请的ByteBuff需要手动释放,大概看了下还是没搞太懂。先记录下,后面有空再仔细看下!
报错如下 LEAK: ByteBuf.release() !!!!⚠️这个报错:
2017-09-17 22:33:40.525 ERROR 15973 --- [ntLoopGroup-2-1] io.netty.util.ResourceLeakDetector : LEAK: ByteBuf.release() was not called before it's garbage-collected. See http://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records: 1
#1:
io.netty.buffer.AdvancedLeakAwareByteBuf.readBytes(AdvancedLeakAwareByteBuf.java:492)
com.cocal.Handle.FakeDhtHandle.channelRead0(FakeDhtHandle.java:59)
com.cocal.Handle.FakeDhtHandle.channelRead0(FakeDhtHandle.java:35)
io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1359)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:935)
io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:93)
io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
java.lang.Thread.run(Thread.java:745)
Created at:
io.netty.util.ResourceLeakDetector.track(ResourceLeakDetector.java:237)
io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:331)
io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:181)
io.netty.buffer.UnsafeByteBufUtil.copy(UnsafeByteBufUtil.java:436)
io.netty.buffer.PooledUnsafeDirectByteBuf.copy(PooledUnsafeDirectByteBuf.java:309)
io.netty.buffer.AbstractByteBuf.copy(AbstractByteBuf.java:1168)
io.netty.channel.socket.DatagramPacket.copy(DatagramPacket.java:47)
com.cocal.Handle.FakeDhtHandle.channelRead0(FakeDhtHandle.java:56)
com.cocal.Handle.FakeDhtHandle.channelRead0(FakeDhtHandle.java:35)
io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1359)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:935)
io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:93)
io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
io.netty.util.concurrent.DefaultThreadFactory$Default
这个提示我这个地方的ByteBuff没有释放
com.cocal.Handle.FakeDhtHandle.channelRead0(FakeDhtHandle.java:56)