1
回答
Netty中EmbeddedChannel.writeInbound为什么会对引用计数减1?
开发十年,就只剩下这套Java开发体系了   

        ByteBuf buf = Unpooled.buffer();
        for (int i = 0; i < 9; i++) {
            buf.writeByte(i);
        }
        ByteBuf input = buf.duplicate();
        EmbeddedChannel channel = new EmbeddedChannel(new FixedLengthFrameDecoder(3));
        assertTrue(channel.writeInbound(input.retain()));
        assertTrue(channel.finish());

        ByteBuf read = (ByteBuf) channel.readInbound();
        assertEquals(buf.readSlice(3), read);
        read.release();

 

    在黄色行,调用了input.retain()使引用计数加1,我理解这是因为channel.writeInbound()方法会使input的引用计数减1,为了确保后续依然能够使用这个ByteBuf才进行了这个操作。

    那么,有两个问题:

    1、为什么要在channel.writeInbound()方法中对引用计数进行减1?

    2、在什么情况下Netty会自动对引用计数进行减1。

举报
pinitianjie
发帖于8个月前 1回/279阅

1、这里只所以要input.retain(),是因为后面要用到这个input做一些验证(见《Netty实战》),而FixedLengthFrameDecoder的父类ByteToMessageDecoder在channelRead中响应消息后,会调用callDecode转换消息,然后对旧消息的引用计数减1导致传入的input的引用计数减1,所以这里在传入前使用input.retain()将其引用计数加1。

2、常见减1情况如下:
(1)如果handler继承自SimpleChannelInboundHandler,用户只需要在ChannelRead0里处理消息,SimpleChannelInboundHandler会自动将引用计数减1,来释放消息。

(2)如果ChannelPipelie里的Handler都没有处理消息导致消息到达ChannelPipele的结尾,DefaultChannelPipeline的实现中,会打印一条信息,然后将消息的引用计数减1,释放消息。代码如下:

    /**
     * Called once a message hit the end of the {@link ChannelPipeline} without been handled by the user
     * in {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)}. This method is responsible
     * to call {@link ReferenceCountUtil#release(Object)} on the given msg at some point.
     */
    protected void onUnhandledInboundMessage(Object msg) {
        try {
            logger.debug(
                    "Discarded inbound message {} that reached at the tail of the pipeline. " +
                            "Please check your pipeline configuration.", msg);
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }

其实,EmbeddedChannel只所以能实现ChannelHandler的单元测试,最关键的也是重写了DefaultChannelPipeline的onUnhandledInboundMessage方法。

顶部