问题
I have a http service with Netty. For a set of requests there is the same reply with just "{}" in http body. I had an idea to avoid creation of new buffer for each such request etc so I've just used:
private static final ByteBuf EMPTY_REPLY = Unpooled.copiedBuffer("{}", CharsetUtil.UTF_8);
in my SimpleChannelInboundHandler. It works only for first query, after it I start to have
WARNING: Failed to mark a promise as success because it has failed already: DefaultChannelPromise@48c81b24(failure: io.netty.handler.codec.EncoderException: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1), unnotified cause:
io.netty.handler.codec.EncoderException: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:106)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738)
at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:801)
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:814)
at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:794)
at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:831)
at travel.ServerHandler.writeResult(ServerHandler.java:475)
so looks like buffer is automatically released after first reply. What is a correct way to have such buffer?
回答1:
When sharing a Netty buffer, you need to follow the rules of basic reference counting, unlike the simple rules of basic garbage collection.
These rules basically boil down to:
- When sending a
ByteBuf
away from your class, callretain()
- If you are done using a
ByteBuf
, callrelease()
Most of the times, when you are done using a bytebuf at the same time as sending it away, you can remove both calls.
Inside you example, when writing your shared ByteBuf
to the socket, you should call retain()
to increment the reference count, since the object is now used in 2 different places.
There is still 1 trick you need to do after calling .retain()
, that is calling .duplicate()
, as this prevents modifications of the reader index from passing to to your base copy, failing to do so gives the problem of the first write succeeded, but after that all subsequent writes will write an empty buffer.
来源:https://stackoverflow.com/questions/45771169/reusing-of-bytebuf-in-netty