IllegalReferenceCount in my custom netty Decoder
我刚开始使用Netty(使用4.0.15.Final)。我想从使用专有协议的现有硬件设备中读取消息。我已经实现了如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | public class Xml2StreamProtocolDecoder extends ByteToMessageDecoder { private static final int LENGTH_OF_START_SENTINEL_IN_BYTES = 1; private static final int LENGTH_OF_END_SENTINEL_IN_BYTES = 1; private static final int LENGTH_OF_LENGTH_FIELD_IN_BYTES = 4; @Override protected void decode( ChannelHandlerContext ctx, ByteBuf in, List<Object> out ) throws Exception { if( in.readableBytes() > LENGTH_OF_START_SENTINEL_IN_BYTES + LENGTH_OF_LENGTH_FIELD_IN_BYTES) { short startSentinel = in.readUnsignedByte(); if (startSentinel != 0x01) { throw new CorruptedFrameException("startsentinel not as expected, was" + startSentinel +" while we expect 0x01" ); } int messageLength = getMessageLength( in ); if( in.readableBytes() >= messageLength + LENGTH_OF_END_SENTINEL_IN_BYTES ) { ByteBuf result = in.slice( in.readerIndex(), messageLength ); in.skipBytes( messageLength ); short endSentinel = in.readUnsignedByte(); if( endSentinel != 0x00 ) { throw new CorruptedFrameException("endsentinel not as expected, was" + endSentinel +" while we expect 0x00" ); } out.add( result ); } else { // Not enough bytes yet in the frame. Wait on next pass with more bytes. } } else { // Not enough bytes yet to read out the length of the frame. Wait on next pass with more bytes. } } private int getMessageLength( ByteBuf in ) { int msglen1 = in.readUnsignedByte(); int msglen2 = in.readUnsignedByte(); int msglen3 = in.readUnsignedByte(); int msglen4 = in.readUnsignedByte(); return ((msglen4 * 256 * 256 * 256) + (msglen3 * 256 * 256) + (msglen2 * 256) + msglen1); } } |
我有一个可以像这样正常工作的单元测试:
1 2 3 4 5 6 | ByteBuf input = Unpooled.buffer(); input.writeBytes( .... ); Xml2StreamProtocolDecoder decoder = new Xml2StreamProtocolDecoder(); EmbeddedChannel channel = new EmbeddedChannel( decoder ); channel.writeInbound( input ); assertThat(channel.inboundMessages()).isNotNull().hasSize( 2 ); |
但是,当我在管道中添加第二个解码器(这是标准的Netty类)以将字节转换为这样的String时:
1 2 | EmbeddedChannel channel = new EmbeddedChannel( decoder, new StringDecoder( Charset.forName("UTF-8" ) ) ); |
然后单元测试失败,但出现以下异常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | Feb 25, 2014 10:11:26 AM io.netty.channel.embedded.EmbeddedChannel recordException WARNING: More than one exception was raised. Will report only the first one and log others. io.netty.handler.codec.DecoderException: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1 at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:153) at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) at com.flir.its.test.Xml2StreamProtocolDecoder2Test.testWith2Messages(Xml2StreamProtocolDecoder2Test.java:188) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:640) at org.testng.internal.Invoker.invokeMethod(Invoker.java:627) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:798) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1102) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:137) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:121) at org.testng.TestRunner.runWorkers(TestRunner.java:1009) at org.testng.TestRunner.privateRun(TestRunner.java:683) at org.testng.TestRunner.run(TestRunner.java:553) at org.testng.SuiteRunner.runTest(SuiteRunner.java:311) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:306) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:268) at org.testng.SuiteRunner.run(SuiteRunner.java:217) at org.testng.TestNG.runSuite(TestNG.java:1062) at org.testng.TestNG.runSuitesLocally(TestNG.java:956) at org.testng.TestNG.run(TestNG.java:874) io.netty.handler.codec.DecoderException: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1 at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:153) at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:338) at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:324) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) at com.flir.its.test.Xml2StreamProtocolDecoder2Test.testWith2Messages(Xml2StreamProtocolDecoder2Test.java:188) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:640) at org.testng.internal.Invoker.invokeMethod(Invoker.java:627) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:798) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1102) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:137) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:121) at org.testng.TestRunner.runWorkers(TestRunner.java:1009) at org.testng.TestRunner.privateRun(TestRunner.java:683) at org.testng.TestRunner.run(TestRunner.java:553) at org.testng.SuiteRunner.runTest(SuiteRunner.java:311) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:306) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:268) at org.testng.SuiteRunner.run(SuiteRunner.java:217) at org.testng.TestNG.runSuite(TestNG.java:1062) at org.testng.TestNG.runSuitesLocally(TestNG.java:956) at org.testng.TestNG.run(TestNG.java:874) at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:75) at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:120) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) Caused by: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1 at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:115) at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:68) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:91) ... 35 more at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:75) at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:120) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) Caused by: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1 at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:115) at io.netty.buffer.AbstractDerivedByteBuf.release(AbstractDerivedByteBuf.java:50) at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:68) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:91) ... 35 more |
为什么会这样?我在
看看ByteBuf :: retain()