Netty4-ByteBuf学习3

版权声明:本文为博主原创文章,转载请注明出处
UnpooledHeapByteBuf源码分析
从类名中就可以看出,当前类是采用的堆内存的形式的字节缓冲区,并且没有基于对象池技术来实现

成员变量中,alloc的类型是ByteBufAllocator,用于为UnpooledHeapByteBuf分配堆内存;byte类型的数组作为缓冲区;tmpNioBuf的类型是ByteBuffer ,用于实现ByteBuf到ByteBuffer的转换

private final ByteBufAllocator alloc;
    byte[] array;
    private ByteBuffer tmpNioBuf;

在AbstractByteBuf类中实现了当写入的字节数不够时依照怎样的规则去重新计算新容量的方法,在本类中实现的是依照返回的新容量去重新分配数组。首先检查newCapacity,内部实现是先去判断checkBounds,即是否需要检查界限,如果需要再去判断newCapacity是否大于0或小于最大容量;然后获得当前byte数组的长度oldCapacity,判断newCapacity和oldCapacity的关系;如果大于,说明,需要重新分配一个数组,将旧数组中的值拷贝到新数组中,并设置新数组和释放旧数组,此时不需要;如果小于,也需要重新分配一个数组,获取当前缓冲区的读指针readerIndex,判断readerIndex和newCapacity的关系,如果小于,再判断写指针writerIndex和newCapacity,如果大于,说明写指针超出了范围,需要将写指针赋值为writerIndex,然后将旧数组中读指针到写指针之间的数据拷贝到新数组中,这是用户还没读取的内容;如果readerIndex>=newCapacity,直接将读写指针都设置为newCapacity,然后设置新数组并释放旧数组

public ByteBuf capacity(int newCapacity) {
        checkNewCapacity(newCapacity);

        int oldCapacity = array.length;
        byte[] oldArray = array;
        if (newCapacity > oldCapacity) {
            byte[] newArray = allocateArray(newCapacity);
            System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
            setArray(newArray);
            freeArray(oldArray);
        } else if (newCapacity < oldCapacity) {
            byte[] newArray = allocateArray(newCapacity);
            int readerIndex = readerIndex();
            if (readerIndex < newCapacity) {
                int writerIndex = writerIndex();
                if (writerIndex > newCapacity) {
                    writerIndex(writerIndex = newCapacity);
                }
                System.arraycopy(oldArray, readerIndex, newArray, readerIndex, writerIndex - readerIndex);
            } else {
                setIndex(newCapacity, newCapacity);
            }
            setArray(newArray);
            freeArray(oldArray);
        }
        return this;
    }

将ByteBuf转换为NIO中的ByteBuffer的方法,直接使用ByteBuffer中wrap方法,设置好读写位置和容量,然后调用slice方法返回当前缓冲区的透视,即读写索引等变量都是独立的,但是缓冲区内容是共享的。

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

PooledDirectByteBuf源码分析

PooledDirectByteBuf与UnpooledDirectByteBuf只是内存分配策略不同,其它功能均相同

由于本类使用了内存池来实现,所以创建一个新对象不需要在内存中新开辟一个地址,需要从RECYCLER中获取,然后设置引用计数值

static PooledDirectByteBuf newInstance(int maxCapacity) {
        PooledDirectByteBuf buf = RECYCLER.get();
        buf.reuse(maxCapacity);
        return buf;
    }

下述copy方法返回一个新的ByteBuf的实例,主要是调用AbstractByteBufAllocator的directBuffer方法,方法里newDirectBuffer会根据AbstractByteBufAllocator不同的子类实现不同的调用,例如如果是基于内存池的实现,那么会从内存池中选取一个实例并进行赋值返回,否则会新申请一个内存。

 public ByteBuf copy(int index, int length) {
        checkIndex(index, length);
        ByteBuf copy = alloc().directBuffer(length, maxCapacity());
        copy.writeBytes(this, index, length);
        return copy;
    }

PooledDirectByteBuf中newDirectBuffer方法的实现。首先取得一个分配内存线程池中的一个实例,获得directArena,然后当directArena不为null时,直接调用allocate返回ByteBuf的一个实例;否则判断当前平台是否有Unsafe的实现,有的话调用UnsafeByteBufUtil的newUnsafeDirectByteBuf方法,否则调用UnpooledDirectByteBuf构造方法

protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
        PoolThreadCache cache = threadCache.get();
        PoolArena<ByteBuffer> directArena = cache.directArena;

        final ByteBuf buf;
        if (directArena != null) {
            buf = directArena.allocate(cache, initialCapacity, maxCapacity);
        } else {
            buf = PlatformDependent.hasUnsafe() ?
                    UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity) :
                    new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
        }

        return toLeakAwareBuffer(buf);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值