netty那些bytebuf踩过的坑

程序超过256个字节以后用抓包工具抓包显示消息已经发送给服务端并且服务端也回发了ack表示已经收到了,但是在read方法里并没有收到消息。
几经辗转发现问题出现在编解码器上,自己定义的解码器是这样的:

ByteBuf heapBuffer = ctx.alloc().heapBuffer();
        in.readBytes(heapBuffer, in.resetReaderIndex().readableBytes());
        out.add(heapBuffer);

问题就出在第二句上了,它的方法描述如下:
netty那些bytebuf踩过的坑_第1张图片
这里使用readbytes方法拷贝bytebuf对象。但是bytebuf在没有分配大小时写大小默认是256。当写入的时候发现长度不够,于是就抛出了异常。在服务器上异常不知道为什么没有打印出来,所以找了很久都没找到原因。
但是每隔一段时间会报:

ERROR|io.netty.util.ResourceLeakDetector] - LEAK: ByteBuf.release() was not called before it's garbage-collected. See http://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records: 
Created at:
    io.netty.buffer.PooledByteBufAllocator.newHeapBuffer(PooledByteBufAllocator.java:314)
    io.netty.buffer.AbstractByteBufAllocator.heapBuffer(AbstractByteBufAllocator.java:166)
    io.netty.buffer.AbstractByteBufAllocator.heapBuffer(AbstractByteBufAllocator.java:152)
    com.montnets.po.conf.CustomDecoder.decode(CustomDecoder.java:42)
    io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
    io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)
    io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
    io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310)
    io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:284)
    io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
    io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
    io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
    io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
    io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
    io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
    io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
    io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
    io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
    io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    java.lang.Thread.run(Thread.java:748)

提示bytebuf在垃圾回收之前没有被释放!在代码里每次用完bytebuf都有释放的,所以一时也不知道什么原因。
但因为上面的问题逻辑大概通透了。
因为调用readBytes()方法的时候异常,所以并没有进入到read方法中,我的bytebuf都是在read中释放的,所以在解码器中创建的这个bytebuf自然是没有被释放的了!
最后看懂的小伙伴应该已经知道解决方法了,就是在调用ByteBuf heapBuffer = ctx.alloc().heapBuffer(); 的时候给它分配大小。ByteBuf heapBuffer = ctx.alloc().heapBuffer(readableBytes);

你可能感兴趣的:(netty)