io.netty.buffer.PooledByteBuf<T>使用内存池中的一块内存作为自己的数据内存,这个块内存是PoolChunk<T>的一部分。PooledByteBuf<T>是一个抽象类型,它有4个派生类:

  • PooledHeapByteBuf, PooledUnsafeHeapByteBuf 使用堆内存的PooledByteBuffer<byte[]>。
  • PooledDirectByteBuf, PooledUnsafeDirectByteBuf 使用直接内存的PooledByteBuf<ByteBuffer>。

初始化

  PooledByteBuf的初始化过程分为两个步骤:创建实例;初始化内存。这两个步骤的代码如下:

复制代码
    protected PooledByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) {         super(maxCapacity);         this.recyclerHandle = recyclerHandle;     }      void init(PoolChunk<T> chunk, long handle, int offset, int length, int maxLength, PoolThreadCache cache) {         init0(chunk, handle, offset, length, maxLength, cache);     }      private void init0(PoolChunk<T> chunk, long handle, int offset, int length, int maxLength, PoolThreadCache cache) {         assert handle >= 0;         assert chunk != null;          this.chunk = chunk;         memory = chunk.memory;         allocator = chunk.arena.parent;         this.cache = cache;         this.handle = handle;         this.offset = offset;         this.length = length;         this.maxLength = maxLength;         tmpNioBuf = null;     }
复制代码

  创建实例时调用的构造方法只是为maxCapacity和recyclerHandler属性赋值,构造方法是protected,不打算暴露到外面。派生类都提供了newInstance方法创建实例,以PooledHeapByteBuf为例,它的newInstance方法实现如下:

复制代码
 1     private static final Recycler<PooledHeapByteBuf> RECYCLER = new Recycler<PooledHeapByteBuf>() {  2         @Override  3         protected PooledHeapByteBuf newObject(Handle handle) {  4             return new PooledHeapByteBuf(handle, 0);  5         }  6     };  7  8     static PooledHeapByteBuf newInstance(int maxCapacity) {  9         PooledHeapByteBuf buf = RECYCLER.get(); 10         buf.reuse(maxCapacity); 11         return buf; 12     }
复制代码

  这里的newInstance使用RECYCLER创建实例对象。Recycler<T>是一个轻量级的,支持循环使用的对象池。当对象池中没有可用对象时,会在第4行使用构造方法创建一个新的对象。

 

  init调用init0初始化数据内存,init0方法为几个内存相关的关键属性赋值:

  • chunk:  PoolChunk<T>对象,这个PooledByteBuf使用的内存就是它的一部分。
  • memory: 内存对象。更准确地说,PooledByteBuf使用的内存是它的一部分。
  • allocator: 创建这个PooledByteBuf的PooledByteBufAllocator对象。
  • cache:  线程专用的内存缓存。分配内存时会优先从这个缓存中寻找合适的内存块。
  • handle:  内存在chunk中node的句柄。chunk使用handle可以计算出它对应内存的起始位置offset。
  • offset:  分配内存的起始位置。
  • length: 分配内存的长度,也是这个PooledByteBuf的capacity。
  • maxLength: 这块内存node的最大长度。当调用capacity(int newCapacity)方法增加capacity时,只要newCapacity不大于这个值,就不用从新分配内存。

  内存初始化完成之后,这个PooledByteBuf可使用的内存范围是memory内存中[offset, offset+length)。idx方法可以把ByteBuf的索引转换成memory的索引:

复制代码
1     protected final int idx(int index) { 2         return offset + index; 3     }
复制代码