美文网首页
使用Netty5.0的一些问题

使用Netty5.0的一些问题

作者: 岁月静好丶丶丶 | 来源:发表于2018-03-09 11:42 被阅读0次

1.在NettyClientHandler中的ChannelRead()读取数据时报IllegalReferenceCountException异常

问题:NettyClientHandler继承的SimpleChannelInboundHandler<Object>类,在执行ChannelRead()中的buf.readBytes(bs)时报以下错误:

DefaultChannelPipeline: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
                                                                               io.netty.util.IllegalReferenceCountException: refCnt: 0
                                                                                   at io.netty.buffer.AbstractByteBuf.ensureAccessible(AbstractByteBuf.java:1150)
                                                                                   at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1133)
                                                                                   at io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:648)
                                                                                   at io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:656)
                                                                                   at com.xianfan.jt808demo.connect.NettyClientHandler.channelRead(NettyClientHandler.java:59)
                                                                                   at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:84)
                                                                                   at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:153)
                                                                                   at io.netty.channel.PausableChannelEventExecutor.invokeChannelRead(PausableChannelEventExecutor.java:86)
                                                                                   at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:389)
                                                                                   at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:956)
                                                                                   at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:127)
                                                                                   at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:514)
                                                                                   at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:433)
                                                                                   at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:387)
                                                                                   at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:351)
                                                                                   at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
                                                                                   at io.netty.util.internal.chmv8.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1412)
                                                                                   at io.netty.util.internal.chmv8.ForkJoinTask.doExec(ForkJoinTask.java:280)
                                                                                   at io.netty.util.internal.chmv8.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:877)
                                                                                   at io.netty.util.internal.chmv8.ForkJoinPool.scan(ForkJoinPool.java:1706)
                                                                                   at io.netty.util.internal.chmv8.ForkJoinPool.runWorker(ForkJoinPool.java:1661)
                                                                                   at io.netty.util.internal.chmv8.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:126)

原因:在netty4中,对象的生命周期由引用计数器控制,ByteBuf就是如此,每个对象的初始化引用计数为1,调用一次release方法,引用计数器会减1,当尝试访问计数器为0的,对象时,会抛出IllegalReferenceCountException,正如ensureAccessible的实现,更加详细的解释可以参考官方文档
AbstractByteBuf.java

protected final void ensureAccessible() {
        if (refCnt() == 0) {
            throw new IllegalReferenceCountException(0);
        }
    }

NettyClientHandler类中的 super.channelRead(ctx, msg);这行代码。追踪调用路径

private void invokeChannelRead(Object msg) {
        try {
            ((ChannelInboundHandler) handler()).channelRead(this, msg);
        } catch (Throwable t) {
            notifyHandlerException(t);
        }
    }

最终调用的代码是:ReferenceCountUtil.release(msg)

public static boolean release(Object msg) {
        if (msg instanceof ReferenceCounted) {
            return ((ReferenceCounted) msg).release();
        }
        return false;
    }

也就是每次super.channelRead(ctx, msg);后,ByteBuf就会调用release()方法,计数器减一,然后在 buf.readBytes(butfs);这行代码就会校验ensureAccessible(),计数器为0,netty认为ByteBuf对象已经释放,就抛出异常。
解决方法:去掉NettyClientHandler中这行代码 super.channelRead(ctx, msg);
ByteBuf对象谁处理谁释放。

相关文章

  • 使用Netty5.0的一些问题

    1.在NettyClientHandler中的ChannelRead()读取数据时报IllegalReferenc...

  • 图解Netty5.0

    前言: 如果知识不能够在短时间内应用那么就很难记住,换句话说没有应用的知识都是你没有掌握的!图解系列相当于在大脑中...

  • ChannelFuture的用法

    该文章基于个人的理解,翻译自netty5.0 API。 综述 ChannelFuture的作用是用来保存Chann...

  • ChannelHandler的用法

    该文章基于个人的理解,翻译自netty5.0 API。 综述 ChannelHandler处理一个I/O even...

  • ChannelPipline的用法

    该文章基于个人的理解,翻译自netty5.0 API。 综述 ChannelPipeline的作用是保存一个Cha...

  • Vue之计算属性computed(二)

    补充说明computed的平时使用的遇到的一些问题 这边通过一个例子来引出computed在使用过程中的一些问题:...

  • setState

    使用以下方法,能够避免一些问题

  • angular 搭建后台发现的bug

    使用angular 搭建后台发现的一些问题 使用post 登录之后可以保存会话的session , 但是使用自己搭...

  • Android ConfigChanges属性详解

    ScrollView 使用遇见的一些问题(横竖屏的切换问题) 当我们写ScrollView (滚动查看) 使用竖...

  • Netty5.0核心之线程模型

    前言: 前面章节我们对Netty的整体结构和使用流程进行了剖析,使用过程中我们首先创建了两个线程组EventLoo...

网友评论

      本文标题:使用Netty5.0的一些问题

      本文链接:https://www.haomeiwen.com/subject/vidpfftx.html