Netty内存管理器ByteBufAllocator及内存分配

王猴卖瓜

共 3520字,需浏览 8分钟

 · 2021-05-02

ByteBufAllocator 内存管理器:

  Netty 中内存分配有一个最顶层的抽象就是ByteBufAllocator,负责分配所有ByteBuf 类型的内存。功能其实不是很多,主要有以下几个重要的API:

public interface ByteBufAllocator {/**分配一块内存,自动判断是否分配堆内内存或者堆外内存。
* Allocate a {@link ByteBuf}. If it is a direct or heap buffer depends on the actual implementation.
*/
ByteBuf buffer();/**尽可能地分配一块堆外直接内存,如果系统不支持则分配堆内内存。
* Allocate a {@link ByteBuf}, preferably a direct buffer which is suitable for I/O.
*/
ByteBuf ioBuffer();/**分配一块堆内内存。
* Allocate a heap {@link ByteBuf}.
*/
ByteBuf heapBuffer();/**分配一块堆外内存。
* Allocate a direct {@link ByteBuf}.
*/
ByteBuf directBuffer();/**组合分配,把多个ByteBuf 组合到一起变成一个整体。
* Allocate a {@link CompositeByteBuf}.If it is a direct or heap buffer depends on the actual implementation.
*/
CompositeByteBuf compositeBuffer();
}

  到这里有些小伙伴可能会有疑问,以上API 中为什么没有前面提到的8 中类型的内存分配API?下面我们来看ByteBufAllocator 的基本实现类AbstractByteBufAllocator,重点分析主要API 的基本实现,比如buffer()方法源码如下:

public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
@Override
public ByteBuf buffer() {
//判断是否默认支持directBuffer
if (directByDefault) {
return directBuffer();
}
return heapBuffer();
}
}

  我们发现buffer()方法中做了判断,是否默认支持directBuffer,如果支持则分配directBuffer,否则分配heapBuffer。directBuffer()方法和heapBuffer()方法的实现逻辑几乎一致,来看directBuffer()方法:

@Override
public ByteBuf directBuffer() {
 //分配大小,初始大小256 默认最大capacity为Integer.MAX
return directBuffer(DEFAULT_INITIAL_CAPACITY, DEFAULT_MAX_CAPACITY);
}
@Override
public ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
if (initialCapacity == 0 && maxCapacity == 0) {
return emptyBuf;
}//校验初始化大小和最大大小
validate(initialCapacity, maxCapacity);
return newDirectBuffer(initialCapacity, maxCapacity);
}
/**
* Create a direct {@link ByteBuf} with the given initialCapacity and maxCapacity.
*/
protected abstract ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity);

  directBuffer()方法有多个重载方法,最终会调用newDirectBuffer()方法,我们发现newDirectBuffer()方法其实是一个抽象方法,最终,交给AbstractByteBufAllocator 的子类来实现。同理,我们发现heapBuffer()方法最终是调用newHeapBuffer()方法,而newHeapBuffer()方法也是抽象方法,具体交给AbstractByteBufAllocator 的子类实现。AbstractByteBufAllocator 的子类主要有两个:PooledByteBufAllocator 和UnpooledByteBufAllocator,下面我们来看AbstractByteBufAllocator 子类实现的类结构图:

  到这里,其实我们还只知道directBuffer、heapBuffer 和pooled、unpooled 的分配规则,那unsafe 和非unsafe是如何判别的呢?其实,是Netty 自动帮我们判别的,如果操作系统底层支持unsafe 那就采用unsafe 读写,否则采用非unsafe 读写。我们可以从UnpooledByteBufAllocator 的源码中验证一下,来看源码:

public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
  @Override
  protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
   return PlatformDependent.hasUnsafe() ? new UnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity)
   : new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
  }

  @Override
  protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
   ByteBuf buf = PlatformDependent.hasUnsafe() ?
   UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity) :
   new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
   return disableLeakDetector ? buf : toLeakAwareBuffer(buf);
  }
}

  我们发现在newHeapBuffer()方法和newDirectBuffer()方法中,分配内存判断PlatformDependent 是否支持Unsafa,如果支持则创建Unsafe 类型的Buffer,否则创建非Unsafe 类型的Buffer。由Netty 帮我们自动判断了。

浏览 49
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报