简体   繁体   中英

Memory leak due to ByteBuffers in Netty

I created a small Netty server to calculate the factorial of a BigInteger and send the results. The code is as follows.

Factorial.java

public class Factorial {

    private int port;

    public Factorial(int port) {
        this.port = port;
    }

    public void run(int threadcount) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup(threadcount);
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ch.pipeline().addLast(new FactorialHandler());
                 }
             })
             .option(ChannelOption.SO_BACKLOG, 128)          
             .childOption(ChannelOption.SO_KEEPALIVE, true); 

            ChannelFuture f = b.bind(port).sync(); 

            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        int port = 15000;
        new Factorial(port).run(Integer.parseInt(args[0]));
    }
}

FactorialHandler.java

public class FactorialHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) { 
        BigInteger result = BigInteger.ONE;
        String resultString;
        for (int i=2000; i>0; i--)
            result = result.multiply(BigInteger.valueOf(i));
        resultString = result.toString().substring(0, 3)+"\n";
        ByteBuf buf = Unpooled.copiedBuffer(resultString.getBytes());
        ctx.write(buf);
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

When I ran this I got the following error

Jun 08, 2018 5:28:09 PM io.netty.util.ResourceLeakDetector reportTracedLeak
SEVERE: 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:

As explained in the given link, I released the ByteBuffer by calling buf.release() in the channelRead method after ctx.flush() .

But when I do that, the server starts throwing the following exception

io.netty.util.IllegalReferenceCountException: refCnt: 0, increment: 1

Can someone please tell me how to fix this issue?

The problem is not the outbound ByteBuf. Outbound ByteBufs are always taken care of for you (See OutboundMessages ). The problem is the inbound ByteBuf. I'm looking at you, FactorialHandler. It extends ChannelInboundHandlerAdapter . Note this from the JavaDoc:

Be aware that messages are not released after the channelRead(ChannelHandlerContext, Object) method returns automatically. If you are looking for a ChannelInboundHandler implementation that releases the received messages automatically, please see SimpleChannelInboundHandler .

Your handler has a signature like this:

public void channelRead(ChannelHandlerContext ctx, Object msg)

That msg, (which you don't use, by the way) is actually a ByteBuf, which is exactly what the JavaDoc note above is warning you about. (In the absence of any other ChannelHandlers, messages will always be instances of ByteBuf.)

So your options are:

  1. Use a SimpleChannelInboundHandler which will clean up that reference for you.
  2. At the end of your handler, release the inbound ByteBuf using ReferenceCountUtil.release(java.lang.Object msg) .

这是因为您不调用msg.release() (msg是ByteBuf的一个实例)。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM