将数据传递给以下处理程序将创建异常

时间:2019-03-11 15:22:52

标签: netty

我正在使用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;
        }
    }

1 个答案:

答案 0 :(得分:0)

MUST NOT呼叫byteBuf.release();,因为解码器将为您完成。