使用Unpooled创建ByteBuf

Unpooled 是 netty 提供的一个工具类,通过它可以方便地创建各种类型的 ByteBuf。需要注意的是,通过 Unpooled 创建的是非池化的 ByteBuf,在注重性能的场景需要使用各种 PooledByteBuf。接下来我们就来看下 Unpooled 类是如何使用的。

Unpooled 提供了一系列的方法用于创建 ByteBuf,根据底层实现的不同,可以将这些 ByteBuf 分为四种类型,分别是 heapBufferdirectBufferwrappedBuffercopiedBuffer

heapBuf

heapBuf 使用的是在 java 堆内存上分配的空间,底层是通过 byte 数组存储数据的,对应的实现类为 UnpooledHeapByteBuf 及其子类。在 UnpooledHeapByteBuf 类中定义了一个 byte[] 类型的数组

1
byte[] array;

根据创建 byte 数组的方式不同,netty 提供了 UnpooledUnsafeHeapByteBufUnpooledHeapByteBuf 两个实现类,其中 UnpooledUnsafeHeapByteBuf 是通过 jdk 提供的 jdk.internal.misc.Unsafe 类对数组进行操作的。

要创建一个 heapBuf,可以使用如下几种方式

1
2
3
4
5
6
7
8
9
10
11
// initialCapacity默认大小256
// maxCapacity默认大小Integer.MAX_VALUE

// 使用默认大小
Unpooled.buffer();

// 指定initialCapacity
Unpooled.buffer(0);

// 指定initialCapacity和maxCapacity
Unpooled.buffer(0, 1);

directBuf

heapBuf 不同的是,directBuf 是在堆外内存分配的。在进行网络 I/O 时,需要将 heapBuf 转换为 directBuf

Unpooled 同样为 directBuf 提供了 3 种创建方式

1
2
3
4
5
6
7
8
9
10
11
// initialCapacity默认大小256
// maxCapacity默认大小Integer.MAX_VALUE

// 使用默认大小
Unpooled.directBuffer();

// 指定initialCapacity
Unpooled.directBuffer(2);

// 指定initialCapacity和maxCapacity
Unpooled.buffer(0, 1);

wrappedBuffer

wrappedBuffer 可以对已有的 byte 数组或 ByteBuf 进行封装,从而提供一个新的视图,用于对原数据进行操作。对原数据内容进行操作会影响创建的 wrappedBuffer,反之亦然。

1
2
3
4
5
6
7
8
9
// 指定byte数组
Unpooled.wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
// 指定byte数组、offset、length
Unpooled.wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 0, 5);
// 多个byte数组
Unpooled.wrappedBuffer(new byte[] { 1 }, new byte[1]));
// 另一个ByteBuf
Unpooled.wrappedBuffer(EMPTY_BUFFER);
// 更多请参考Unpooled及UnpooledTest

copiedBuffer

copiedBuffer 是对原数据进行深拷贝生成的 ByteBuf。和 wrappedBuffer 不同的是,它与原数据是独立的,对原数据进行修改不会影响生成的 copiedBuffer,反之亦然。

1
2
3
4
5
6
7
8
9
10
// 原数据是基础类型,方法名为copy*
Unpooled.copyInt(1);
Unpooled.copyShort(42);
Unpooled.copyLong(42);
// ...

// 原数据是byte数组、字符串、ByteBuffer、ByteBuf等
Unpooled.copiedBuffer(new byte[8]);
Unpooled.copiedBuffer(new ByteBuf[] { wrappedBuffer(new byte[] { 1, 2, 3 })});
// ...