我正在使用Netty 4.1.34.Final。
我得到了引用计数异常,并尝试从异常发生的地方进行调试。 (已经运行带有偏执泄漏检测功能,但这对任何方式都没有帮助。)
通过反复试验,我找到了以下代码:
LOGGER.trace("{}(before fire): byteBuf({})",loggerName,byteBuf.refCnt() );
@Override protected void decode( ChannelHandlerContext ctx, ByteBuf byteBuf, List list ) throws Exception
{
if ( LOGGER.getLevel() == Level.TRACE )
{
byteBuf.touch( String.format( "%s.decode(beginn)", loggerName ) );
}
if ( active == true )
{
ByteBuf copiedBuffer = byteBuf.copy();
LOGGER.debug( "{}:input({} bytes): {}", loggerName, copiedBuffer.readableBytes(), copiedBuffer.toString( StandardCharsets.US_ASCII ) );
copiedBuffer.release();
}
if ( LOGGER.getLevel() == Level.TRACE )
{
byteBuf.touch( String.format( "%s.decode(before fire)", loggerName ) );
}
// byteBuf.retain(2); does not help
ctx.fireChannelRead( byteBuf );
if ( LOGGER.getLevel() == Level.TRACE )
{
byteBuf.touch( String.format( "%s.decode(after fire)", loggerName ) );
}
}
if ( byteBuf.readableBytes() > 0 )
{
ctx.fireChannelRead( byteBuf );
}
LOGGER.trace("{}(after fire): byteBuf({})",loggerName,byteBuf.refCnt() );
会产生以下日志:
2019-03-11 15:46:58.942 TRACE [pGroup-2-6] [wth] DebugInput(before fire): byteBuf(1)
2019-03-11 15:46:58.942 DEBUG [pGroup-2-6] [wth] RawDecoder size byteBuff: 29 bytes writeIndex: 995
2019-03-11 15:46:58.942 TRACE [pGroup-2-6] [wth] RawDecoder(refcount): byteBuf(1)
2019-03-11 15:46:58.942 TRACE [pGroup-2-6] [wth] RawDecoder(refcount): byteBuf(1)
2019-03-11 15:46:58.943 TRACE [pGroup-2-6] [wth] RawDecoder(refcount): result(1)
2019-03-11 15:46:58.943 INFO [pGroup-2-6] [wth] com.example.netty.TrackerServer.protocol.WATCH.WatchHandler exception
io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.buffer.AbstractReferenceCountedByteBuf.toLiveRealCnt(AbstractReferenceCountedByteBuf.java:190) ~[TrackerServer-running.jar:0.0.1]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release0(AbstractReferenceCountedByteBuf.java:142) ~[TrackerServer-running.jar:0.0.1]
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:133) ~[TrackerServer-running.jar:0.0.1]
at io.netty.buffer.WrappedByteBuf.release(WrappedByteBuf.java:1029) ~[TrackerServer-running.jar:0.0.1]
at io.netty.buffer.SimpleLeakAwareByteBuf.release(SimpleLeakAwareByteBuf.java:102) ~[TrackerServer-running.jar:0.0.1]
at io.netty.buffer.AdvancedLeakAwareByteBuf.release(AdvancedLeakAwareByteBuf.java:941) ~[TrackerServer-running.jar:0.0.1]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:286) ~[TrackerServer-running.jar:0.0.1]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:359) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:345) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:337) [TrackerServer-running.jar:0.0.1]
at com.example.netty.TrackerServer.protocol.WATCH.DebugInput.decode(DebugInput.java:54) [TrackerServer-running.jar:0.0.1]
at io.netty.handler.codec.ByteToMessageCodec$1.decode(ByteToMessageCodec.java:42) [TrackerServer-running.jar:0.0.1]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:502) [TrackerServer-running.jar:0.0.1]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:441) [TrackerServer-running.jar:0.0.1]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:278) [TrackerServer-running.jar:0.0.1]
at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:359) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:345) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:337) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1408) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:359) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:345) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:796) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:427) [TrackerServer-running.jar:0.0.1]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:328) [TrackerServer-running.jar:0.0.1]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:905) [TrackerServer-running.jar:0.0.1]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [TrackerServer-running.jar:0.0.1]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_191]
2019-03-11 15:46:58.943 TRACE [pGroup-2-6] [wth] DebugInput(rafter fire): byteBuf(0)
这是问题吗? (根据文档,移交给下一个时,我不应该释放)
更新
我找到了原因,但我仍然不知道出了什么问题。 我删除了FIRST解码器(RawDecoder)
ChannelInitializer的摘录:
ByteBuf delimiter = Unpooled.copiedBuffer( BRACKET );
//channel.pipeline().addLast( new RawDecoder( 4 * 1024, false, delimiter ) );
channel.pipeline().addLast( new BasicHeader() );
channel.pipeline().addLast( new DetailedHeader() );
channel.pipeline().addLast( new WatchHandler() );
RawDecoder:
public class RawDecoder extends DelimiterBasedFrameDecoder
{
private Logger LOGGER = LogManager.getLogger( TRACK_GLOBALS.HANDLER_WATCH );
private String loggerName = "";
public RawDecoder( int maxFrameLength, boolean stripDelimiter, ByteBuf delimiter )
{
super( maxFrameLength, stripDelimiter, delimiter );
this.setSingleDecode( true );
String tokens[] = this.getClass().getName().split( "\\." );
if ( tokens.length > 0 )
{
loggerName = tokens[ tokens.length - 1 ];
}
else
{
loggerName = this.getClass().getName();
}
LOGGER.info( loggerName + " instantiated" );
}
@Override
protected Object decode( ChannelHandlerContext ctx, ByteBuf byteBuf )
throws Exception
{
ByteBuf result = null;
if ( byteBuf != null )
{
LOGGER.debug( "{} size byteBuff: {} bytes writeIndex: {}",
loggerName,
byteBuf.readableBytes(),
byteBuf.writableBytes() );
if ( LOGGER.getLevel() == Level.TRACE )
{
byteBuf.touch( String.format( "%s.decode(begin)", loggerName ) );
}
int endIndex = byteBuf.indexOf( byteBuf.readerIndex(), byteBuf.writerIndex(), ( byte ) ']' ) + 1;
if ( endIndex > 0 )
{
result = ctx.alloc().buffer();
while ( byteBuf.readerIndex() < endIndex )
{
Byte b1 = byteBuf.readByte();
if ( b1 == '}' )
{
Byte b2 = byteBuf.readByte();
switch ( b2 )
{
case 0x01:
b1 = ( byte ) '}';
break;
case 0x02:
b1 = ( byte ) '[';
break;
case 0x03:
b1 = ( byte ) ']';
break;
case 0x04:
b1 = ( byte ) ',';
break;
case 0x05:
b1 = ( byte ) '*';
break;
default:
throw new IllegalArgumentException( String.format(
"unexpected byte at %d: 0x%02x", byteBuf.readerIndex() - 1, b2 ) );
}
}
result.writeByte( b1 );
}
}
else
{
LOGGER.debug( "{} ignore byteBuffer because of missing ]", loggerName );
}
if ( LOGGER.getLevel() == Level.TRACE )
{
byteBuf.touch( String.format( "%s.decode(before fire)", loggerName ) );
}
byteBuf.release();
}
else
{
LOGGER.debug( "{}: got object {}", loggerName, byteBuf == null ? "null" : byteBuf.getClass().getName() );
}
if ( LOGGER.getLevel() == Level.TRACE )
{
byteBuf.touch( String.format( "%s.decode(exit)", loggerName ) );
}
return result;
}
}
答案 0 :(得分:0)
您MUST NOT
呼叫byteBuf.release();
,因为解码器将为您完成。