Reactive Programmming
Java NIO - Direct Byte Buffer, Heap ByteBuffer
재심
2025. 1. 11. 18:24
Java 1.0에 포함된 Input/Output Stream에는 BufferedInputStream, BufferedOutputStream이라는 구현체가 있다.
내부적으로 버퍼를 사용하는데, 이 버퍼는 JVM Heap에 존재하는 버퍼이다.
그리고 실제로 리소스를 읽어오려면 커널 영역의 버퍼를 통해 복사를 해와야 하는데 이 과정에서 CPU 자원을 사용하게 된다.
반면 커널 영역의 버퍼를 바로 사용할 경우 Disk Controller에 의해 CPU 도움 없이 리소스를 버퍼로 바로 복사할 수 있다.
Java 1.4에서 등장한 Java NIO에서는 Channel과 Buffer를 통해 리소스와 통신을 하게 되며
ByteBuffer를 활용하는 경우 DirectByteBuffer, HeapByteBuffer 2가지로 제공한다.
특성 | DirectByteBuffer | HeapByteBuffer |
메모리 위치 | JVM 힙 메모리 | 네이티브 메모리 (JVM 힙 외부) |
메모리 관리 | GC가 관리 | GC의 관리 범주가 아님. 명시적 해제 필요. |
생성 방법 | ByteBuffer.allocate() | ByteBuffer.allocateDirect() |
성능 | 낮음 | 높음 (대규모 I/O 작업에 최적화) |
메모리 할당/해제 속도 | 빠름 | 느림 (JVM에서 관리되지 않아 비용이 많이 드는 system call을 통해야 한다) |
예제 코드
public static void main(String[] args) {
ByteBuffer heapByteBuffer = ByteBuffer.allocate(1024);
ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(1024);
log.info("heapByteBuffer isDirect: {}", heapByteBuffer.isDirect());
log.info("directByteBuffer isDirect: {}", directByteBuffer.isDirect());
File file = new File(Objects.requireNonNull(FIleInputStreamExample.class
.getClassLoader()
.getResource("file-channel.txt"))
.getFile());
try(FileChannel fileChannel = FileChannel.open(file.toPath())){
fileChannel.read(heapByteBuffer);
heapByteBuffer.flip();
log.info("heapByteBuffer로 읽기");
CharBuffer heapByteBufferResult = StandardCharsets.UTF_8.decode(heapByteBuffer);
log.info("heapByteBufferResult: {}", heapByteBufferResult);
// 포지션을 0으로 초기화
fileChannel.position(0);
log.info("directByteBuffer로 읽기");
fileChannel.read(directByteBuffer);
directByteBuffer.flip();
CharBuffer directByteBufferResult = StandardCharsets.UTF_8.decode(directByteBuffer);
log.info("directByteBufferResult: {}", directByteBufferResult);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
heapByteBuffer.clear();
directByteBuffer.clear();
}
}
결과
18:21:52.063 [main] INFO example.nio.buffer.ByteBufferMain -- heapByteBuffer isDirect: false
18:21:52.064 [main] INFO example.nio.buffer.ByteBufferMain -- directByteBuffer isDirect: true
18:21:52.065 [main] INFO example.nio.buffer.ByteBufferMain -- heapByteBuffer로 읽기
18:21:52.065 [main] INFO example.nio.buffer.ByteBufferMain -- heapByteBufferResult: abcdefghigjlmidfg
18:21:52.065 [main] INFO example.nio.buffer.ByteBufferMain -- directByteBuffer로 읽기
18:21:52.065 [main] INFO example.nio.buffer.ByteBufferMain -- directByteBufferResult: abcdefghigjlmidfg