Skip to content

Instantly share code, notes, and snippets.

@GloryAlex
Created June 26, 2021 14:18
Show Gist options
  • Save GloryAlex/0dd4a5b6fedbd93c1ffd74920d6add11 to your computer and use it in GitHub Desktop.
Save GloryAlex/0dd4a5b6fedbd93c1ffd74920d6add11 to your computer and use it in GitHub Desktop.

ByteBuf本质上是一个字节数组,但根据存放位置不同,它有几种不同的操作模式。

堆缓冲区

数据存储在JVM的堆空间内。此时可以直接操作数据。

ByteBuf buf = ...// get ByteBuf
if(buf.hasArray()){
    //ByteBuf in heap
    byte[] array = buf.array();
    int length = buf.readableBytes();//get readable length
    int offset = buf.arrayOffset()+buf.readerIndex();
    handleArray(array,offset,length);//your method
}

直接缓冲区

数据存储在JVM的堆外内存。可以避免每次调用本地I/O前都将缓冲区的内容复制到一个临时的缓冲区。ByteBuffer类采用了此种实现,其Javadoc指出:

直接缓冲区的内容将会驻留在常规的会被垃圾回收的堆之外。

不过,相比于堆内内存而言,其分配和释放代价较大。而且,使用时必须复制到堆内

ByteBuf buf = ...// get ByteBuf
int length = buf.readableBytes();//get readable length
if(!buf.hasArray()){
    //ByteBuf in heap
    byte[] array = buf.array()
    int offset = buf.arrayOffset()+buf.readerIndex();
    handleArray(array,offset,length);//your method
}

复合缓冲区

复合缓冲区提供了多个ByteBuf的一个聚合视图。在Netty中主要是通过CompositeByteBuf类实现的。它提供了将多个缓冲区表示为一个缓冲区的抽象。

在同时含有堆上和堆外内存的ByteBuf时,对CompositeByteBuf类调用hasArray()方法会返回false。

例如,考虑一个由两部分组成的消息:HTTP消息,它由头部和主体构成,而这两部分由不同的模块生成。因此,每个消息都需要重新构建头部,但其主体可能是可为多个消息复用的。 以下展示了构建CompositeByteBuf的复合缓冲区模式

//构建CompositeByteBuf
CompositeByteBuf buf = Unpooled.compositeBuffer();
ByteBuf headBuf = ...//get from backing or direct
ByteBuf bodyBuf = ...//get from backing or direct
buf.addComponents(headBuf,bodyBuf);
...//do something
buf.removeComponents(0);//remove the index 0 ByteBuf(the first component)
for(var message:buf){
    System.out.println(buf.toString());
}

由于可能不能直接访问其原始数组,因此在使用上类似于直接缓冲区模式。以下展示了访问CompositeByteBuf数据的操作。

//访问CompositeByteBuf
CompositeByteBuf compBuf = ...//get CompositeByteBuf
int length = compBuf.readableBytes();
byte[] array = new byte[length];
compBuf.getBytes(compBuf.readerIndex(),array);// copy CompositeByteBuf to new array
handleArray(compBuf,0,array.length);//your method

在套接字的I/O操作中,Netty也使用了CompositeByteBuf来优化由于JDK缓冲区所带来的性能及内存使用率的惩罚。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment