netty那些bytebuf踩过的坑

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

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

问题就出在第二句上了,它的方法描述如下:
这里写图片描述
这里使用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中的ByteBuf是一个可扩展的字节容器,它提供了一系列的API来方便地读取和写入字节数据。下面是一些常见的ByteBuf使用API: 1. 创建ByteBuf对象 可以使用Unpooled工具类来创建ByteBuf对象,例如: ```java ByteBuf buf = Unpooled.buffer(10); ``` 上面的代码创建了一个容量为10的ByteBuf对象。 2. 写入数据 可以使用write方法向ByteBuf中写入数据,例如: ```java buf.writeByte(1); buf.writeShort(2); buf.writeInt(3); buf.writeLong(4); buf.writeFloat(5.0f); buf.writeDouble(6.0); buf.writeBytes("hello".getBytes()); ``` 上面的代码依次向ByteBuf中写入了一个字节、一个短整型、一个整型、一个长整型、一个单精度浮点数、一个双精度浮点数和一个字符串。 3. 读取数据 可以使用read方法从ByteBuf中读取数据,例如: ```java byte b = buf.readByte(); short s = buf.readShort(); int i = buf.readInt(); long l = buf.readLong(); float f = buf.readFloat(); double d = buf.readDouble(); byte[] bytes = new byte[5]; buf.readBytes(bytes); String str = new String(bytes); ``` 上面的代码依次从ByteBuf中读取了一个字节、一个短整型、一个整型、一个长整型、一个单精度浮点数、一个双精度浮点数和一个字符串。 4. 获取可读字节数 可以使用可读字节数方法来获取当前ByteBuf中可读的字节数,例如: ```java int readableBytes = buf.readableBytes(); ``` 5. 释放ByteBuf 使用完ByteBuf对象后,需要手动调用release方法释放对象,例如: ```java buf.release(); ``` 上面的代码释放了ByteBuf对象,释放后的ByteBuf不能再被使用。
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值