-
修改方案:
byteBuf.retain();
ByteBuf后面添加这个retain()
,这个添加原则是这样,如果你消耗了一次ByteBuf,你的下游Handler还需要再次消耗的话,就需要添加这个retain()
,以此类推,一定要要注意添加的时机,不然的话可能需要自己手动释放; -
原因分析:这个错误是因为
ByteBuf
的已经被逻辑释放了,重复释放导致的;Netty
为了防止内存泄漏,使用引用计数的方式计算;这个引用计数一般再ByteBuf
创建的时候会有一次,任何一次的读,写操作都会导致引用数-1;其次,Netty
本身也提供了对ByteBuf
的自动回收机制,所以这样的话,如果不注意,很容易出现这个错误;这个retain
就会增加一次引用;回到我自己的项目案例:-
我创建了一个顶级的父类
NioWebSocketFrameHandler
,用来处理WebSocketFrame
数据帧数据,进行最初的数据分发处理;下面是比较关键的方法:
-
这里我将数据投递到下一个
handler
,这里会消耗一次ByteBuf
;(所以理论上这里的ByteBuf
是可以被回收了);我们继续看下一个处理器,用来处理二进制的数据帧,红框框的位置就是出现异常的位置
-
前面我们说过,ByteBuf的每一次读取都会消耗一次引用,再上游的时候,就已经消耗了一次引用,而
ByteBuf
的引用是整个Pipeline
共享的,所以这里的ByteBuf肯定是不能再引用数-1操作的,引用数已经是0了(这个操作是netty自动完成的),所以就出现了异常错误;
-
-
最后补充一句,当Bytefue引用数为0的时候,Netty会自动回收,所以有时候会出现空指针异常,也是这个原因;源码分析就这里就不分析了,感兴趣的可以去看看;