一文读懂netty对javabytebuf的增强

一、JDKByteBuffer的缺点

1.无法动态扩容:长度是固定,不能动态扩展和收缩,当数据大于ByteBuffer容量时,会发生索引越界异常。

2.API使用复杂:读写的时候需要手工调用flip()和rewind()等方法,使用时需要非常谨慎的使用这些api,否则很容易出现错误。

二、ByteBuf做的增强方面

1.API操作便捷性

2.动态扩容

3.多种ByteBuf实现

4.高效的零拷贝机制

三、netty中对ByteBuf操作

ByteBuf三个重要的属性:capacity容量、readerIndex读取位置、writeindex写入位置。提供了两个指针变量来支持顺序读和写操作,分别为readerIndex和写操作writeIndex。

代码实例:

public class ByteBufDemo {
    @Test
    public void apiTest() {
        //  +-------------------+------------------+------------------+
        //  | discardable bytes |  readable bytes  |  writable bytes  |
        //  |                   |     (CONTENT)    |                  |
        //  +-------------------+------------------+------------------+
        //  |                   |                  |                  |
        //  0      <=       readerIndex   <=   writerIndex    <=    capacity

        // 1.创建一个非池化的ByteBuf,大小为10个字节
        ByteBuf buf = Unpooled.buffer(10);
        System.out.println("原始ByteBuf为====================>" + buf.toString());
        System.out.println("1.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 2.写入一段内容
        byte[] bytes = {1, 2, 3, 4, 5};
        buf.writeBytes(bytes);
        System.out.println("写入的bytes为====================>" + Arrays.toString(bytes));
        System.out.println("写入一段内容后ByteBuf为===========>" + buf.toString());
        System.out.println("2.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 3.读取一段内容
        byte b1 = buf.readByte();
        byte b2 = buf.readByte();
        System.out.println("读取的bytes为====================>" + Arrays.toString(new byte[]{b1, b2}));
        System.out.println("读取一段内容后ByteBuf为===========>" + buf.toString());
        System.out.println("3.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 4.将读取的内容丢弃
        buf.discardReadBytes();
        System.out.println("将读取的内容丢弃后ByteBuf为========>" + buf.toString());
        System.out.println("4.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 5.清空读写指针
        buf.clear();
        System.out.println("将读写指针清空后ByteBuf为==========>" + buf.toString());
        System.out.println("5.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 6.再次写入一段内容,比第一段内容少
        byte[] bytes2 = {1, 2, 3};
        buf.writeBytes(bytes2);
        System.out.println("写入的bytes为====================>" + Arrays.toString(bytes2));
        System.out.println("写入一段内容后ByteBuf为===========>" + buf.toString());
        System.out.println("6.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 7.将ByteBuf清零
        buf.setZero(0, buf.capacity());
        System.out.println("将内容清零后ByteBuf为==============>" + buf.toString());
        System.out.println("7.ByteBuf中的内容为================>" + Arrays.toString(buf.array()) + "\n");

        // 8.再次写入一段超过容量的内容
        byte[] bytes3 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
        buf.writeBytes(bytes3);
        System.out.println("写入的bytes为====================>" + Arrays.toString(bytes3));
        System.out.println("写入一段内容后ByteBuf为===========>" + buf.toString());
        System.out.println("8.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");
}

 四、动态扩容

capacity默认值:256字节、最大值:Integer.MAX_VALUE(2GB);write*方法调用时,通过AbstractByteBuf.ensureWritable()进行检查。容量计算方法:AbstractByteBufAllocator.calculateNewCapacity(新capacity的最小要求,capacity最大值)根据capacity的最小值要求,对应有两套计算方法:

          1.没超过4兆:从64字节开始,每次增加一倍,直至计算出来的newCapacity满足新容量最小要求。实例:当前大小256,已写250,继续写10字节数据,需要的容量最小要求是261,则新容量是64*2*2*2 = 512。

          2.超过4兆:新容量 = 新容量最小要求/4兆 * 4兆 + 4兆。实例:当前大小3兆,已写3兆,继续写2兆数据,需要的容量最小要求是5兆,则新容量是9兆(不能超过最大值)。

五、丰富的byteBuf实现

netty中根据3个纬度,可以划分出8中byteBuf的实现:

堆外/堆内是否池化访问方式具体实现类备注
heap堆内unpoolsafeUnpooledHeapByteBuf数组实现
unsafeUnpooledUnsafeHeapByteBufunsafe类直线操作内存
poolsafePooledHeapByteBuf 
unsafePooledUnsafeHeapByteBuf 
direct堆外unpoolsafeUnpooledDirectByteBufNIO DirectByteBuffer
unsafeUnpooledUnsafeDirectByteBuf 
poolsafePooledDirectByteBuf 
unsafePooledUnsafeDirectByteBuf 

在使用中,都是通过ByteBufAllocator分配器进行申请,同时分配器具备有内存管理的功能。

六、零拷贝机制

netty的零拷贝机制,是一种应用层的实现。和底层JVM、操作系统内存机制并无过多关联。

  • CompositeByteBuf,将多个ByteBuf合并为一个逻辑上的ByteBuf,避免了各个ByteBuf之间的拷贝。

  • wrapedBuffer()方法,将byte[]数组包装成ByteBuf对象

  • slice()方法。将一个ByteBuf对象切分成多个ByteBuf对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值