PooledByteBuf源码分析

1.成员变量

先来看一下PooledByteBuf的类声明

abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf 

为什么要加模版呢?
他的一个成员protected T memory;由于不知道的T是什么数据类型,所以定义了模板类可以从他的字类中看出来

final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer>
final class PooledHeapByteBuf extends PooledByteBuf<byte[]>

在前面的学习中,很容易知道,基于内存的ByteBuf是通过操作ByteBuffer的position来实现读写等操作的,而给予堆的ByteBuf是通过Byte数组来实现读写等操作的,因此声明<T>

成员变量有

 private final Recycler.Handle<PooledByteBuf<T>> recyclerHandle;

    protected PoolChunk<T> chunk;
    protected long handle;
    protected T memory;
    protected int offset;
    protected int length;
    int maxLength;
    Thread initThread;
    private ByteBuffer tmpNioBuf;

resyclerHandle可以理解为垃圾收集器,负责分配回收内存

PoolChunk<T> chunk可以理解为一个很大的内存区域的一个实例,这个类的成员中又一个PoolArean,就是内存中的一大片区域
netty为了集中管理内存的分配和释放,同时提高分配和释放内存的性能,预先申请一大片内存,然后提供分配和释放接口来使用,这样一来,就能不需要频繁地进行系统的申请和释放内存,应用程序的性能就会大大提升。

2. 初始化

void init(PoolChunk<T> chunk, long handle, int offset, int length, int maxLength) {
        assert handle >= 0;
        assert chunk != null;

        this.chunk = chunk;
        this.handle = handle;
        memory = chunk.memory;
        this.offset = offset;
        this.length = length;
        this.maxLength = maxLength;
        setIndex(0, 0);
        tmpNioBuf = null;
        initThread = Thread.currentThread();
    }

可以知道,memory实际上就是chunk中的数据,initThread实际上就是当前的进程。

3.动态扩展内存

我们在前面的UnpooledHeapByteBuf和UnpooledDirectByteBuf中都看到了这个方法,一个是进行array的增大,一个是对ByteBuf的扩展。

public final ByteBuf capacity(int newCapacity) {
        ensureAccessible();

        // If the request capacity does not require reallocation, just update the length of the memory.
        if (chunk.unpooled) {
            if (newCapacity == length) {
                return this;
            }
        } else {
            if (newCapacity > length) {
                if (newCapacity <= maxLength) {
                    length = newCapacity;
                    return this;
                }
            } else if (newCapacity < length) {
                if (newCapacity > maxLength >>> 1) {
                    if (maxLength <= 512) {
                        if (newCapacity > maxLength - 16) {
                            length = newCapacity;
                            setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity));
                            return this;
                        }
                    } else { // > 512 (i.e. >= 1024)
                        length = newCapacity;
                        setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity));
                        return this;
                    }
                }
            } else {
                return this;
            }
        }

1.如果chunk内存区是unpooled(没有实现内存池)的话,只有当newCapacity == length时直接返回,其他情况都要重新分配内存。
2.如果chunk内存区实现了内存池,当新的容量大于原来的容量,且小于最大容量时,直接设置原来的容量为新的容量就行。
3.如果新的容量小于原来的容量,那么就要进行减容处理了,先把最大容量>>>1,向右位位移一位(除2),然后根据除2以后的最大容量和新容量对比,分别进行不同的操作。

4.分配回收内存

来看三个方法

 @Override
    public final ByteBufAllocator alloc() {
        return chunk.arena.parent;
    }
   @Override
    protected final void deallocate() {
        if (handle >= 0) {
            final long handle = this.handle;
            this.handle = -1;
            memory = null;
            boolean sameThread = initThread == Thread.currentThread();
            initThread = null;
            chunk.arena.free(chunk, handle, maxLength, sameThread);
            recycle();
        }
    }
 private void recycle() {
        recyclerHandle.recycle(this);
    }

第一个方法返回ByteBufAllocator对象
第二个方法先销毁原来的内存区,然后重新分配
第三个方法直接回收内存区

总的来说在这个类很容易理解,由于它实现了分配回收内存,还有动态扩展缓存的方法,所以它的字类PooledHeapByteBuf和PooledDirectByteBuf也就不用在实现这些方法啦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值