netty UnpooledHeapByteBuf类

UnpooledHeapByteBuf类

UnpooledHeapByteBuf类的类图如下所示,UnpooledHeapByteBuf继承自AbstractReferenceCountedByteBuf类,UnpooledHeapByteBuf是一个基于JVM堆内存进行内存分配的缓冲区,是一个非池化的实现,所以在每次IO读写的时候都会创建一个UnpooledHeapByteBuf对象。基于堆内存的缓冲区的特点是分配和销毁速度很快,但是在进行IO读写的时候多一次从内核空间向用户空间复制的过程,故其在IO读写的场景下性能较低。

UnpooledHeapByteBuf对字节数据的存储数据是大端顺序

在这里插入图片描述

属性

ByteBuf的分配器,ByteBufAllocator接口的所有实现类都是现成安全的
private final ByteBufAllocator alloc;
byte[] array;//支撑数组
private ByteBuffer tmpNioBuf;//JDK Nio包中的ByteBuffer对象

构造函数

/**
* alloc:ByteBuf分配器
* initialCapacity:缓冲区的初始化容量
* maxCapacity:缓冲区的最大容量
*
*/
public UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
    super(maxCapacity);//设置缓冲区的最大容量

    if (initialCapacity > maxCapacity) {//校验参数的合法性
        throw new IllegalArgumentException(String.format(
                "initialCapacity(%d) > maxCapacity(%d)", initialCapacity, maxCapacity));
    }

    this.alloc = checkNotNull(alloc, "alloc");//非空校验
    setArray(allocateArray(initialCapacity));//开辟数组并将其赋给缓冲区对象
    setIndex(0, 0);//设置缓冲区的读写索引
}
/**
* alloc:ByteBuf分配器
* initialArray:缓冲区的初始化数组
* maxCapacity:缓冲区的最大容量
*
*/
protected UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int maxCapacity) {
    super(maxCapacity);//设置缓冲区的最大容量

    checkNotNull(alloc, "alloc");//非空校验
    checkNotNull(initialArray, "initialArray");//非空校验
    if (initialArray.length > maxCapacity) {//校验参数的合法性
        throw new IllegalArgumentException(String.format(
                "initialCapacity(%d) > maxCapacity(%d)", initialArray.length, maxCapacity));
    }

    this.alloc = alloc;
    setArray(initialArray);
    setIndex(0, initialArray.length);//设置缓冲区的读写索引
}

allocateArray(int initialCapacity)和setArray(byte[] initialArray)方法如下:

protected byte[] allocateArray(int initialCapacity) {
    return new byte[initialCapacity];
}

private void setArray(byte[] initialArray) {
    array = initialArray;
    tmpNioBuf = null;
}

设置缓冲区的容量

UnpooledHeapByteBuf#capacity(int newCapacity)方法的大致逻辑如下:

1、如果newCapacity == oldCapacity则不用做任何操作,直接返回

2、如果newCapacity > oldCapacity,表示需要做扩容操作,执行扩容操作时,读写索引索引不需要被重置,只需要执行数组拷贝即可

3、如果newCapacity > oldCapacity,表示需要做缩容操作,此时需要再做如下判断

​ 3.1如果newCapacity >= writerIndex,则不需要修改读写索引,直接执行数组复制即可

​ 如下图所示:无需修改读写索引,直接进行数组拷贝操作即可
在这里插入图片描述
在这里插入图片描述

3.2 如果newCapacity < writerIndex,将写索引设置为newCapacity,读索引为newCapacity和readerIndex二者的最小值

​ 如下图所示,newCapacity < writerIndex,此时需要重新设置读写指针
在这里插入图片描述

​ 执行读写指针重置并拷贝数组后得到的新的数组如下图橙色部分所示:​
在这里插入图片描述

@Override
public ByteBuf capacity(int newCapacity) {
    checkNewCapacity(newCapacity);
    byte[] oldArray = array;
    int oldCapacity = oldArray.length;
    if (newCapacity == oldCapacity) {
        return this;
    }

    int bytesToCopy;
    if (newCapacity > oldCapacity) {
        bytesToCopy = oldCapacity;
    } else {
        trimIndicesToCapacity(newCapacity);
        bytesToCopy = newCapacity;
    }
    byte[] newArray = allocateArray(newCapacity);
    System.arraycopy(oldArray, 0, newArray, 0, bytesToCopy);//native方法
    setArray(newArray);
    freeArray(oldArray);
    return this;
}

字节数组的复制

UnpooledHeapByteBuf类对于字节数组的复制的实现是直接调本地方法System.arraycopy完成的

@Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
    checkSrcIndex(index, length, srcIndex, src.length);//合法性校验
    System.arraycopy(src, srcIndex, array, index, length);
    return this;
}

将字节数组转换为jdk nio包下的ByteBuffer

Netty的实现也是调用ByteBuffer的wrap方法完成的,与ByteBuffer不同的是netty又调用的slice()方法,ByteBuffer#slice()方法的作用是创建一个源缓冲区的浅拷贝,从源缓冲区的position开始。

@Override
public ByteBuffer nioBuffer(int index, int length) {
    ensureAccessible();
    return ByteBuffer.wrap(array, index, length).slice();
}

释放缓冲区的实现

@Override
protected void deallocate() {
    freeArray(array);
    array = EmptyArrays.EMPTY_BYTES;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值