我在扩展 ReplayingDecoder 的 DecodeEventHandler 类中遇到 ResourceLeakDetector 异常。我很难理解应该何时何地释放任何方法的 BytBuf。是否需要释放传递过来的ByteBuf?我尝试释放 header、eventBody 和 AttachedData ByteBuf 对象,但这在我的代码中后来产生了问题。代码是...
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception
{
switch (state())
{
case READ_HEADER:
ByteBuf header = byteBuf.readBytes(BaseEvent.EVENT_HEADER_SIZE);
newEvent = new BaseEvent(header.nioBuffer());
checkpoint(EventDecoderState.READ_BODY);
// Fall through
case READ_BODY:
ByteBuf eventBody = byteBuf.readBytes(newEvent.getEventHeaderBodySize() - BaseEvent.EVENT_HEADER_SIZE);
newEvent.setEventBody(eventBody.nioBuffer());
checkpoint(EventDecoderState.READ_ATTACHED_DATA);
// Fall through
case READ_ATTACHED_DATA:
ByteBuf attachedData = byteBuf.readBytes(newEvent.getAttachedDataSize());
newEvent.clearAttachedData();
newEvent.addAttachedData(attachedData.nioBuffer());
list.add(newEvent);
checkpoint(EventDecoderState.READ_HEADER);
}
}
该方法从第 23 行开始。我收到的异常是...
2016-06-07 13:30:49.783 [ERROR] (nioEventLoopGroup-7-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: 2 #2: io.netty.buffer.AdvancedLeakAwareByteBuf.nioBuffer(AdvancedLeakAwareByteBuf.java:669) com.oakgate.netty.DecodeEventHandler.decode(DecodeEventHandler.java:30) io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:376) io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245) io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:354) io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:145) io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:354) io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:145) io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266) io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:354) io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:145) io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:1078) io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:117) io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:527) io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:484) io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:398) io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:370) io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:742) io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:145) java.lang.Thread.run(Thread.java:745) #1: io.netty.buffer.AdvancedLeakAwareByteBuf.writeBytes(AdvancedLeakAwareByteBuf.java:561) io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:790) io.netty.handler.codec.ReplayingDecoderByteBuf.readBytes(ReplayingDecoderByteBuf.java:576) com.oakgate.netty.DecodeEventHandler.decode(DecodeEventHandler.java:29) io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:376) io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245) io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:354) io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:145) io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:354) io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:145) io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266) io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:354) io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:145) io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:1078) io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:117) io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:527) io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:484) io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:398) io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:370) io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:742) io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:145) java.lang.Thread.run(Thread.java:745) Created at: io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:271) io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:179) io.netty.buffer.AbstractByteBufAllocator.buffer(AbstractByteBufAllocator.java:115) io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:789) io.netty.handler.codec.ReplayingDecoderByteBuf.readBytes(ReplayingDecoderByteBuf.java:576) com.oakgate.netty.DecodeEventHandler.decode(DecodeEventHandler.java:29) io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:376) io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245) io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:354) io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:145) io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:354) io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:145) io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266) io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83) io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:154) io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:354) io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:145) io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:1078) io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:117) io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:527) io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:484) io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:398) io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:370) io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:742) io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:145) java.lang.Thread.run(Thread.java:745)
其他信息
当我释放通过调用 byteBuf.readBytes() 创建的每个 ByteBuf( header 、eventBody 和 AttachedData)时,我稍后在处理事件时会遇到问题。我调用 nioBuffer() 从 ByteBuf 创建一个 ByteBuffer,看起来释放原始 ByteBuf 会影响 ioBuffer() 调用中的 ByteBuffer。根据文档,返回的缓冲区与 bytebuf 共享内容,这很可能意味着我还无法释放它。我是否需要保留每个 ByteBuf,然后在处理事件时释放它?除非有其他方法可以做到这一点,否则看起来就是这样。
最佳答案
您正在通过 byteBuf.readBytes
创建新的 ByteBuf
,它们需要被释放。
您的案例READ_HEADER示例:
:
case READ_HEADER:
ByteBuf header = null;
try {
header = byteBuf.readBytes(BaseEvent.EVENT_HEADER_SIZE);
newEvent = new BaseEvent(header.nioBuffer());
checkpoint(EventDecoderState.READ_BODY);
} finally {
if(header != null)
header.release();
}
// Fall through
关于netty - ReplayingDecoder 中的 ResourceLeakDetector 异常。我什么时候释放ByteBuf?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37690912/