说明
- 当ByteBuf的引用计数为0的时候,如果用该buffer的readableBytes()函数判断可读字节数,可能返回的值不是0,而是一个大于0的数。但这个只是假象,如果此时去读buffer的数据,会抛出IllegalReferenceCountException异常。
- 当ByteBuf的引用计数为0的时候,如果用ByteBufUtil的isAccessible(ByteBuf buffer)函数判断,那么结果返回false,表示不可访问。
- 处理方式:1)先判断是否可以访问,可以访问时,再判断可读字节数。2)也可以不判断是否可以访问,而是将访问ByteBuf数据的代码放在try…catch代码块内,捕获抛出的异常。3)不判断是否可以访问,也不捕获访问ByteBuf数据抛出的异常,而是允许异常抛出,使程序终止。
代码示例
ByteBuf的可读字节数不为0,但不可访问,读取数据抛出异常
package com.thb;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
public class Demo {
public static void main(String[] args) {
// 创建一个ByteBuf
ByteBuf buf = Unpooled.buffer();
buf.writeByte(0x68);
// 此时引用计数是1
System.out.println("before release, buf.refCnt: " + buf.refCnt());
// 可读字节数是1
System.out.println("before release, buf.readableBytes: " + buf.readableBytes());
// 可以访问
System.out.println("before release, buf isAccessible: " + ByteBufUtil.isAccessible(buf));
buf.release();
// 引用计数是0
System.out.println("after release, buf.refCnt: " + buf.refCnt());
// 可读字节数是1,但这是假象
System.out.println("after release, buf.readableBytes: " + buf.readableBytes());
// 不可访问
System.out.println("after release, buf isAccessible: " + ByteBufUtil.isAccessible(buf));
// 因为不可访问,所以访问数据会抛出异常
buf.readByte();
}
}
运行输出:
before release, buf.refCnt: 1
before release, buf.readableBytes: 1
before release, buf isAccessible: true
after release, buf.refCnt: 0
after release, buf.readableBytes: 1
after release, buf isAccessible: false
Exception in thread "main" io.netty.util.IllegalReferenceCountException: refCnt: 0
at io.netty.buffer.AbstractByteBuf.ensureAccessible(AbstractByteBuf.java:1454)
at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1440)
at io.netty.buffer.AbstractByteBuf.readByte(AbstractByteBuf.java:730)
at com.thb.Demo.main(Demo.java:29)