[Java, Netty] PooledUnsafeDirectByteBuf을 Byte[]로 변환하기
카테고리: Java + Kotlin
PooledUnsafeDirectByteBuf
PooledUnsafeDirectByteBuf는 Netty에서 제공하는 풀링(pooling) 및 unsafe 메모리 액세스를 통해 성능을 향상시키려는 목적으로 디자인된 바이트 버퍼(ByteBuf) 중 하나이다.
EchoServer 예제
Netty의 EchoServer 예제를 살펴보면 EchoServerHandler.java에 아래와 같은 부분이 있다.
@Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ctx.write(msg);
}
...
}
Netty ~ 4.0
이때, object msg는 PooledUnsafeDirectByteBuf를 자료형으로 갖는데 4.0 버전까지는 아래와 같은 방식으로 버퍼에 직접 접근이 가능했다.
Bytebuf buf = ByteBuf.readBytes(2);
byte[] b = buf.array();
Netty 4.1 ~
하지만, 4.1 버전부터 UnsupportedOperationException: direct buffer 오류를 출력하며 직접 접근을 막는다. 이는 기본 버퍼 타입이 heap에서 direct로 변경되었기 때문인데 heap 버퍼의 경우 소켓에 버퍼를 쓰게 될 때 direct 버퍼로 한 번 복사한 뒤에 써야 하기 때문에 성능상 불이익이 있기 때문이다.
따라서 아래와 같은 방식으로 버퍼의 내용을 배열을 할당한 뒤 복사하여 사용해야 한다.
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf buf = (ByteBuf) msg;
byte[] array;
int offset;
int length;
if (buf.hasArray()) {
array = buf.array();
offset = buf.arrayOffset() + buf.readerIndex();
length = buf.readableBytes();
} else {
array = new byte[buf.readableBytes()];
offset = 0;
length = array.length;
buf.getBytes(buf.readerIndex(), array);
}
ctx.write(msg);
}