slice/retainedSlice/readRetainedSlice

文章详细解释了Netty中的ByteBuf类,包括其可读写字节数、内存管理(slice、retainedSlice和readRetainedSlice的区别)、以及索引操作。着重展示了不同切片方法对原始ByteBuf的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来聊聊Netty的ByteBuf

Netty源码ByteBuf详解

@Slf4j
public class D {

    @Test
    public void test_01() {

        ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(256);


        log.info("可读: {}", buf.readableBytes());
        log.info("可写: {}", buf.writableBytes());
        System.out.println("---------------------");
        buf.writeBytes("halo".getBytes());

        int length = 2;
        int index = 0;

        // ByteBuf sliceBuf = buf.slice();
        // ByteBuf sliceBuf = buf.slice(index, length);
        // ByteBuf sliceBuf = buf.retainedSlice();
        // ByteBuf sliceBuf = buf.retainedSlice(index, length);
        ByteBuf sliceBuf = buf.readRetainedSlice(length);


        log.info("buf可读: {}", buf.readableBytes());
        log.info("buf可写: {}", buf.writableBytes());
        log.info("buf#readerIndex: {}", buf.readerIndex());
        log.info("buf#writerIndex: {}", buf.writerIndex());
        log.info("buf#toString(): {}", buf.toString());
        log.info("buf#内容: {}", buf.toString(Charset.defaultCharset()));

        System.out.println("-----------------------------");

        log.info("sliceBuf可读: {}", sliceBuf.readableBytes());
        log.info("sliceBuf可写: {}", sliceBuf.writableBytes());
        log.info("sliceBuf#readerIndex: {}", sliceBuf.readerIndex());
        log.info("sliceBuf#writerIndex: {}", sliceBuf.writerIndex());
        log.info("sliceBuf#toString: {}", sliceBuf.toString());
        log.info("sliceBuf#内容: {}", sliceBuf.toString(Charset.defaultCharset()));

        buf.release();
        sliceBuf.release();


        // buf.getByte(0);
        // buf.readByte();
        // buf.writeBytes("halo".getBytes());
        // sliceBuf.getByte(0);
        // sliceBuf.readByte();
        // sliceBuf.writeBytes("halo".getBytes());

        // 如果buf的refCnt为0, 则不能再写入, 也不能再读取了

        // 如果buf通过slice()方法得到sliceBuf后,
        //      得到的sliceBuf的范围为buf的readerIndex到writerIndex之间的字节数据, 可写为0
        //      当buf被release了, 则sliceBuf不能再写入, 也不能再读取了;
        //      当sliceBuf被release了, 则buf不能再写入, 也不能再读取了;

        // 如果buf通过slice(index, length)方法得到sliceBuf后,
        //      得到的sliceBuf的范围为buf的指定index到length长度的字节数据, 可写为0
        //      当buf被release了, 则sliceBuf不能再写入, 也不能再读取了;
        //      当sliceBuf被release了, 则buf不能再写入, 也不能再读取了;

        // 从上面可以知道: buf经过slice之后得到的sliceBuf, 当其中任何1个被释放掉, 另外1个就不能读写了

        // 如果buf通过retainedSlice()方法得到sliceBuf后,
        //      得到的sliceBuf的范围为buf的readerIndex到writerIndex之间的字节数据, 可写为0
        //      当buf被release了, 则buf仍能读写, sliceBuf仍能读取; 当buf再次被release, 则buf不能读写了, sliceBuf也不能被读写了;
        //      当sliceBuf被release了, 则buf可以读写, sliceBuf不能再读写了, 但是sliceBuf可以使用getByte(index)/setByte(index,value)/toString(charset)方法, 并且sliceBuf修改之后的buf也会修改;
        //      从这些结果可知: buf经过retainedSlice之后得到的sliceBuf, 会让原来的buf的引用+1, sliceBuf与原buf之间仍然共享同一内存
        //                    因此, 可以理解为将原来的buf调用完slice()之后, 再对原来的buf调用retained()
        // retainedSlice(index, length)方法就是在retainedSlice()的基础上多了划分指定区间的功能

        // 如果buf通过readRetainedSlice(length)方法得到sliceBuf后,
        //      得到的sliceBuf的范围为buf的readerIndex到length长度的字节数据, 可写为0, 并且buf的readerIndex会员原来的基础上加上length
        //      当buf被release了, 则buf仍能读写, sliceBuf仍能读取; 当buf再次被release, 则buf不能读写了, sliceBuf也不能被读写了;
        //      当sliceBuf被release了, 则buf可以读写, sliceBuf不能再读写了, 但是sliceBuf可以使用getByte(index)/setByte(index,value)/toString(charset)方法, 并且sliceBuf修改之后的buf也会修改;
        //      当buf被release了, 则buf仍能读写, sliceBuf仍能读取; 此时, 当sliceBuf被释放, 则buf不能读写了, sliceBuf也不能被读写了;
        //      从这些结果可知: buf经过readRetainedSlice(length)得到的sliceBuf, 会让原来的buf引用+1,  sliceBuf与原buf之间仍然共享同一内存
        //                    因此, 可以理解为将原来的buf调用完retainedSlice(readerIndex, length)之后, 再对原来的buf调用readBytes(length)
        System.out.println("-----------------------------");

        System.out.println(buf);
        System.out.println(sliceBuf);

    }

    @Test
    public void test_02() {

        byte[] bytes = ByteBufUtil.decodeHexDump("000E");
        System.out.println(bytes[1]);

    }

    @Test
    public void test_03() {

        ByteBuf buf = ByteBufAllocator.DEFAULT.directBuffer(256);

        buf.writeBytes("halo".getBytes());

        byte[] bytes = new byte[2];

        // 将byteBuf从索引为1的字节开始, 读取bytes.length个字节到bytes中(如果超出可读范围会抛越界异常), 不会修改buf的readerIndex
        buf.getBytes(1, bytes);

        // 输出: al
        System.out.println(new String(bytes));

    }

    @Test
    public void test_04() {

        ByteBuf buf = ByteBufAllocator.DEFAULT.directBuffer(2, 4);

        byte[] bytes = "halo".getBytes();

        // 将bytes数组中的bytes.length个字节写到buf中, 不能超过buf的最大容量
        buf.writeBytes(bytes);

        System.out.println(buf.toString(StandardCharsets.UTF_8));

    }

    @Test
    public void test_05() {

        ByteBuf buf = ByteBufAllocator.DEFAULT.directBuffer(256);

        buf.writeBytes("halo".getBytes());

        byte[] bytes = new byte[5];
        
        // 从buf的readerIndex 加上bytes.length长度范围内的字节读取到bytes数组中, 这个范围不能超过writerIndex
        buf.readBytes(bytes);

        System.out.println(bytes);


    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值