开发者社区 问答 正文

netty的一个引用计数器释放的问题, 报异常?报错

io.netty.util.IllegalReferenceCountException: refCnt: 0
	at io.netty.handler.codec.mqtt.MqttPublishMessage.content(MqttPublishMessage.java:49)
	at io.netty.handler.codec.mqtt.MqttPublishMessage.release(MqttPublishMessage.java:95)
	at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:84)
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:112)
	at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83)
	at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:163)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:155)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:276)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:263)
	at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:83)
	at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:163)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:155)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:950)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:125)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:510)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:467)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:381)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:353)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:742)
	at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
	at java.lang.Thread.run(Thread.java:745)



上面的是报错信息.

下面是PublishHandler 代码, 它前面还有一个ConnectHandler

@Override
    protected void channelRead0(ChannelHandlerContext ctx, MqttMessage msg) throws Exception {
        if (msg instanceof MqttPublishMessage) {
            MqttPublishMessage publishMessage = (MqttPublishMessage) msg;

            try {
                doPublish(publishMessage);

                int messageId = publishMessage.variableHeader().messageId();
                MqttPubAckMessage ack = buildPubAck(messageId);
                sendResponse(ctx, ack);
            } finally {
                publishMessage.retain();
                //publishMessage.release();
            }

        } else {
            ctx.fireChannelRead(msg);
        }
    }



看finlly里面的, 我一开始写的是publishMessage.release(), 因为, 这个时候, 这个message已经不需要, 根据没有其他地方再使用了就销毁的原因, 我让他释放. 合乎逻辑啊.

但是为什么是publicMessage.retain()呢? 这不是将message的引用计数加1 吗? 本来是1现在是2, 哪里会去减呢?

2. 另外, 这里的报错信息,没有我的业务类的任何信息,我怎么调试啊, 调试了半天没有找到?

请大家帮忙看看

展开
收起
爱吃鱼的程序员 2020-06-10 14:32:42 1034 分享 版权
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB
    @SimpleFast
    请帮忙看看
    你看你的 PublishHandler类继承的是不是simple开头的一个类,这个类会自动的调用 release方法,所以你再进行调用的话,会导致该异常出现回复 @兮风古道:两位大哥说的对..我看了SimpleInBoundChannel的文档,确实是这样的.我想知道为什么要这样设计呢?直接让我们自己实现的子类用完了自己释放不好吗?回复 @plugin:你要想自己管理引用计数,就不要继承SimpleInBoundChannelnetty的官方资料上对于这种引用计数的对象的管理,有两个原则1当一个组件要把引用计数对象传给另一组件时,该对象何时销毁由另一组件决定2如果一个组件内部的引用计数对象不会再被其他组件访问了,则销毁他。对于我这里的问题,我不明白为什么要SimpleInBoundChannel类里去release它,而不是让我自己的子类去做
    2020-06-10 14:33:00
    赞同 展开评论