Netty - Buffer 1

首先要清楚 Buffer 和 Cache 的区别。

???

  • ByteBuf
  • ByteBufHolder
  • ByteBufAllocator

ByteBuf

在JDK中缓冲区可以理解为只有一个 position 指针用于读&写,详情可以参考 文章,与JDK不同的是 Netty 中缓冲区具有两个指示位置的指针分别用于 读|写:

  • readerIndex 读操作时,该值增加
  • writerIndex 写操作时,该值增加

初始状态这两个指针都指向位置 0,通常 read write 操作会自动的增加这两个指针值,get set 这类相对位置的操作则不会改变指针值。

当然 ByteBuf 会有一个 maximum 用来标示缓冲区的最大容量,默认情况下为 Integer.MAX_VALUE

Netty 中缓冲区有3种类型:

  • Heap Buffer
  • Direct Buffer
  • Composite Buffer

Heap Buffer 堆缓冲区

HeapBuffer 也是最常用的 ByteBuf,顾名思义,它的数据存储空间分配在 JVM 的堆内存区域。实际上是一个内部数组,并且 HeapBuffer 是可以访问其内部数组的。

访问 non-heap(非堆内存数组)时会导致 UnsupportedOperationException,所以在访问 ByteBuf 内部数组时,需要通过 hasArray() 来检验。

ByteBuf heapBuf = Unpooled.copiedBuffer("Netty IO", Charset.forName("UTF-8"));
if (heapBuf.hasArray()) {
    System.out.println("Has Array");
    byte[] array = heapBuf.array();
    int offset = heapBuf.arrayOffset();
    int length = heapBuf.readableBytes();
    System.out.println("offset="+ offset +" length="+length);
        
    System.out.println("capacity=" + heapBuf.capacity());
    System.out.println("isDirect=" + heapBuf.isDirect());
    System.out.println("isReadable=" + heapBuf.isReadable());
    System.out.println("isReadOnly=" + heapBuf.isReadOnly());
} else {
    System.out.println("Hasn't Array");
}

Direct Buffer 直接缓冲区

直接缓冲区指的是内存空间不在堆空间上,而是直接在内存上分配的。

在进行 Socket 数据传输的时候,使用直接缓冲区是一个不错的选择,因为如果使用的是非直接缓冲区的话,JVM需要先把缓冲区拷贝到直接缓冲区,然后再进行 Socket 传输。

其缺点在于:

  1. 直接缓冲区的内存分配和回收代价会比堆内缓冲区要高。(这也是为什么 Netty 会支持缓冲池的原因)
  2. 使用直接缓冲区的话,我们就无法像操作堆缓冲区一样来直接操作其内部数组了。
ByteBuf directBuf = ByteBufAllocator.DEFAULT.directBuffer();
directBuf.writeBytes("Netty IO".getBytes());
if (!directBuf.hasArray()) {
    System.out.println("No Array");
    int length = directBuf.readableBytes();
    byte[] copyArray = new byte[length];
    directBuf.getBytes(0,copyArray);
            
    System.out.println((char)copyArray[0]);
} else {
    System.out.println("Has Array");
}

Composite Buffer 复合缓冲区

复合缓冲区实际上是将多个缓冲区实例组合起来,并向外提供一个统一视图。像是一个缓冲区的 List。

因为符合缓冲区只是多个缓冲区的视图,所以缓冲区的 hasArray() 方法将会返回 false。

ByteBuf heapBuf = Unpooled.copiedBuffer("Heap", Charset.forName("UTF-8"));
ByteBuf directBuf = ByteBufAllocator.DEFAULT.directBuffer().writeBytes("Direct".getBytes());

CompositeByteBuf compositeBuf = ByteBufAllocator.DEFAULT.compositeBuffer();
compositeBuf.addComponent(heapBuf);
compositeBuf.addComponent(directBuf);

你可能感兴趣的:(Netty - Buffer 1)