在用netty框架做采集程序時,控制台有時會輸出 WARN
io.netty.channel.AbstractChannelHandlerContext -Failed to mark a promise as failure because it has failed already: DefaultChannelPromise@630e0515(failure: java.lang.IndexOutOfBoundsException: srcIndex: 0), unnotified cause: java.lang.IndexOutOfBoundsException: srcIndex: 0 異常。
在剛開始的時候以為是程序哪個地方出現下標越界的異常,排查后未發現相關問題,緊接着查看控制台打印的其他錯誤異常,發現有一個
io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1的異常,百度后才知道其異常的根本原因是:
這是因為Netty有引用計數器的原因,自從Netty 4開始,對象的生命周期由它們的引用計數(reference counts)管理,而不是由垃圾收集器(garbage collector)管理了。ByteBuf是最值得注意的,它使用了引用計數來改進分配內存和釋放內存的性能。在我們創建ByteBuf對象后,它的引用計數是1,當你釋放(release)引用計數對象時,它的引用計數減1,如果引用計數為0,這個引用計數對象會被釋放(deallocate),並返回對象池。當嘗試訪問引用計數為0的引用計數對象會拋出IllegalReferenceCountException異常:
/**
* Should be called by every method that tries to access the buffers content to check
* if the buffer was released before.
*/
protected final void ensureAccessible() {
if (checkAccessible && refCnt() == 0) {
throw new IllegalReferenceCountException(0);
}
}
解決辦法
方法1:在合適的地方,補上 ByteBuf.retain(),這個意思是 讓netty的引用計數+1
方法2:使用ChannelInboundHandlerAdapter替代SimpleChannelInboundHandler
本項目中是extends ChannelInboundHandlerAdapter,但還是會出現IllegalReferenceCountException異常。

猜想有可能是發送命令時創建了ByteBuf,而引起的此異常,修改代碼后問題解決。
