Nettyのメモリリークの問題

12906 ワード

nettyをテストしたときにこの問題を発見しました
LEAK: ByteBuf.release() was not called before it's garbage-collected. Enable advanced leak reporting to find out where the leak occurred. To enable advanced leak reporting, specify the JVM option '-Dio.netty.leakDetectionLevel=advanced' or call ResourceLeakDetector.setLevel() See http://netty.io/wiki/reference-counted-objects.html for more information. |

2つの方法でログ・レベルを変更
  • ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);
  • -Dio.netty.leakDetectionLevel=advanced

  • テストを続行:
     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: 5
    #5:
        io.netty.buffer.AdvancedLeakAwareByteBuf.toString(AdvancedLeakAwareByteBuf.java:697)
        io.netty.handler.codec.http.websocketx.TextWebSocketFrame.text(TextWebSocketFrame.java:94)
        com.qingqing.livebroker.server.handler.WebsocketMsgHandler.channelRead(WebsocketMsgHandler.java:76)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler$1.channelRead(WebSocketServerProtocolHandler.java:146)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:244)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
        io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
        io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
        io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
        io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
        io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
        io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
        io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
        java.lang.Thread.run(Thread.java:745)
    #4:
        io.netty.buffer.AdvancedLeakAwareByteBuf.release(AdvancedLeakAwareByteBuf.java:45)
        io.netty.buffer.DefaultByteBufHolder.release(DefaultByteBufHolder.java:73)
        io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:59)
        io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:91)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler$1.channelRead(WebSocketServerProtocolHandler.java:146)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:244)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
        io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
        io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
        io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
        io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
        io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
        io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
        io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
        java.lang.Thread.run(Thread.java:745)
    #3:
        io.netty.buffer.AdvancedLeakAwareByteBuf.retain(AdvancedLeakAwareByteBuf.java:709)
        io.netty.buffer.DefaultByteBufHolder.retain(DefaultByteBufHolder.java:61)
        io.netty.handler.codec.http.websocketx.WebSocketFrame.retain(WebSocketFrame.java:76)
        io.netty.handler.codec.http.websocketx.TextWebSocketFrame.retain(TextWebSocketFrame.java:109)
        io.netty.handler.codec.http.websocketx.TextWebSocketFrame.retain(TextWebSocketFrame.java:25)
        io.netty.handler.codec.http.websocketx.WebSocketProtocolHandler.decode(WebSocketProtocolHandler.java:37)
        io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler.decode(WebSocketServerProtocolHandler.java:114)
        io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler.decode(WebSocketServerProtocolHandler.java:51)
        io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler$1.channelRead(WebSocketServerProtocolHandler.java:146)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:244)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
        io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
        io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
        io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
        io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
        io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
        io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
        io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
        java.lang.Thread.run(Thread.java:745)
    #2:
        io.netty.buffer.AdvancedLeakAwareByteBuf.forEachByte(AdvancedLeakAwareByteBuf.java:625)
        io.netty.handler.codec.http.websocketx.Utf8Validator.check(Utf8Validator.java:74)
        io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.checkUTF8String(WebSocket08FrameDecoder.java:464)
        io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.decode(WebSocket08FrameDecoder.java:337)
        io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:370)
        io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:230)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
        io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
        io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
        io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
        io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
        io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
        io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
        io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
        java.lang.Thread.run(Thread.java:745)
    #1:
        io.netty.buffer.AdvancedLeakAwareByteBuf.setByte(AdvancedLeakAwareByteBuf.java:253)
        io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.unmask(WebSocket08FrameDecoder.java:429)
        io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.decode(WebSocket08FrameDecoder.java:302)
        io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:370)
        io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:230)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
        io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
        io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
        io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
        io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
        io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
        io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
        io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
        java.lang.Thread.run(Thread.java:745)
    Created at:
        io.netty.buffer.UnpooledByteBufAllocator.newDirectBuffer(UnpooledByteBufAllocator.java:55)
        io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:155)
        io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:146)
        io.netty.buffer.AbstractByteBufAllocator.buffer(AbstractByteBufAllocator.java:83)
        io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.decode(WebSocket08FrameDecoder.java:263)
        io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:370)
        io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:230)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)
        io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
        io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
        io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
        io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
        io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
        io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
        io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
        io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
        java.lang.Thread.run(Thread.java:745) | 
    

    ByteBufは、Nettyで主にデータbyte[]に使用されるパッケージクラスであり、主にHeap ByteBufとDirect ByteBufに分けられる.メモリの分配回収および発生したメモリの破片を減らすため、NettyはPooledByteBufAllocatorを提供して回収可能なByteBufを分配するために使用し、PooledByteBufAllocatorを池と見なすことができ、必要に応じて中からByteBufを取得し、使い終わったら戻すことでパフォーマンスを向上させる.もちろんそれに対応しているのはUnpooledByteBufAllocatorで、その名の通りUnpooledは池に入れないので、このディスペンサによって割り当てられたByteBufによって、池に戻す必要はなくJVM自身GCで回収されます.Nettyでは、ChannelHandlerContextとChannelによって取得されたAllocatorはデフォルトでPooledなので、メモリの漏洩を避けるために、適切なタイミングで解放する必要があります.テキストリンク:https://blog.csdn.net/u012807459/article/details/77259869
    間違った3行目は私のChannelInboundHandlerAdapterがbyteを取得して解放していないことに位置することができます.
    //  
    textWebSocketFrame.release();
    //  
    //ctx.fireChannelRead(msg);
    

    以上の2つの方式はいずれもByteBufを解放することができる.