12

I came across this query: Create a ByteBuf in Netty 4.0 about conversion from byte[] to ByteBuf and ByteBuffer to ByteBuf. I was curious to know about the conversion the other way:

io.netty.buffer.ByteBuf to java.nio.ByteBuffer

and how to do it efficiently, with minimal/no copying? I did some reading and with some trial and error I found this inefficient way of converting it (with two copies):

// io.netty.handler.codec.http.FullHttpRequest fullHttpRequest;
ByteBuf conByteBuf = fullHttpRequest.content ();                  
int numReadBytes = conByteBuf.readableBytes ();
conBytes = new byte[numReadBytes];
conByteBuf .readBytes (conBytes);                                // First Copy
ByteBuffer conByteBuffer = ByteBuffer.allocate (conBytes.length);
conByteBuffer.put (conByteBuf);                                  // Second Copy

My question is, can we avoid one or both the copies and make the internal buffer of ByteBuffer to use the internal buffer of ByteBuf.

Thanks!

3 Answers 3

14

You should be able to use ByteBuf.nioBuffers(). Which will return a view of the ByteBuf as an array of ByteBuffer objects.

In most cases this array will only have one element, but in some of the more complicated implementations of ByteBuf there may be multiple underlying ByteBuffer objects and ByteBuf.nioBuffers() can return them as-is instead of merging them as would a call to ByteBuf.nioBuffer().

You can tell ahead of time what the array length will be by using ByteBuf.nioBufferCount()

Sign up to request clarification or add additional context in comments.

3 Comments

This doesn't address when it is backed by a byte[]
@Dev, When you use ByteBuf.nioBuffers() or ByteBuf.nioBuffer() to return a view of the ByteBuf as an array of ByteBuffer objects or a single ByteBuffer object, what happens if you were to release the ByteBuf? It appears that problems will occur with the created ByteBuffer object when this happens since the ByteBuf and ByteBuffer share the underlying data.
So ByteBuf.nioBuffer() automatically merges them into one? I could just call this instead of iterating through the array in nioBuffers()?
7

You can at least use ByteBuffer.wrap() to avoid the second copying.

2 Comments

Can we still avoid the first copy?
It seems Dev's response below will help eliminate even that.
2

Not particularly efficient but doing the trick:

public static ByteBuffer toNioBuffer(ByteBuf buffer) {
    if (buffer.isDirect()) {
        return buffer.nioBuffer();
    }
    final byte[] bytes = new byte[buffer.readableBytes()];
    buffer.getBytes(buffer.readerIndex(), bytes);
    return ByteBuffer.wrap(bytes);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.