简体   繁体   中英

Netty memory leak for http server. When to release message?

Unless using SimpleChannelInboundHandler channelRead0 , one should release input packets if ctx.fireChannelRead is not called.

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    log.error("receive {}", msg);
    if (msg instanceof FullHttpRequest) {            
        FullHttpRequest req = (FullHttpRequest) msg;
        ReferenceCountUtil.release(msg);
        clientChannel.writeAndFlush(new RequestWrapper(req, foo)); 
    }
}

clientChannel.writeAndFlush when success, push requestWrapper into a queue. netty does not show LEAK warnings , but as described in jvm out of memory , the Old Gen of this project increases, event with ReferenceCountUtil.release(msg) .

  1. if http input message is not released, why official example does not call release explicitly?
  2. in channelRead , if received msg is set in another bean, and then this bean is passed on by ctx.fireChannelRead , should I call release for this msg, like code above?
  3. if a new object is passed on by ctx.fireChannelRead(newObject) , should I call release(newObject) in the next handler?

like this:

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    ctx.fireChannelRead("hello world");
}

public void channelRead(ChannelHandlerContext ctx, Object msg) {
    assert "hello world".equals(msg);
    ReferenceCountUtil.release(msg); // is this necessary if it is created in the former handler?
}
  1. How about write operation, should I also call release for write object?

like this:

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
    ctx.write("bye", promise);
}

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
    assert "bye".equals(msg);
    // should I call ReferenceCountUtil.release(msg); ?
    ctx.write(“bye bye”, promise);
}

1.Maybe it's a bug.Honestly,I don't know.But it must release the obj if you do not call ctx.fireChannelRead() in your Handler(interrupt the handlers' chain). Or the TailContext will release the obj.

2.You can't release the msg in this Handler,if you do,maybe other context will allocate the obj that used in this context.You should release the object only if the bean is end;

3.Your new object is not implement ReferenceCounted ,so why you need to release the object?Just return false but do nothing in ReferenceCountUtil as follow:

    public static boolean release(Object msg) {
    if (msg instanceof ReferenceCounted) {
        return ((ReferenceCounted) msg).release();
    }
    return false;
}

4.You are not necessary need to release the write object because netty will release after send the object

After hours of experiments and debugged into the source code, about the 4th point: ReferenceCountUtil.refCnt :

public static int refCnt(Object msg) {
    return msg instanceof ReferenceCounted ? ((ReferenceCounted) msg).refCnt() : -1;
}

because every netty handler is a responsible chain pattern, write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) can actually have any object msg (argument delivered along the chain). It only needs to manually call release in this situation:

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
    FullHttpResponse fullHttpResponse = ...
    ctx.write(fullHttpResponse, promise);
}

The instantiation of FullHttpResponse finally calls ByteBuffer.allocate which comes with a refCnt plus 1.

If in the following handlers, due to exceptions or userFiredEvents , this FullHttpResponse is not sent out by calling:

    ctx.write(msg, promise);
    ctx.flush();

then FullHttpResponse needs to be manually released. The last but not the least, if a FullHttpResponse has refCnt released, it does not send out. From the point of client, request hangs.

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