-
humongous object javaJava/자바를 더 깊게 2025. 3. 15. 19:43반응형
humongous object 란?
humongous는 거대한 이라는 사전적 의미를 가지고 있습니다.
humongous object는 이 글에서는 앞으로 거대한 객체로 칭하겠습니다.
하지만 거대하다는 것을 추상적인 의미를 가집니다.
누군가는 1KB 정도의 객체를 거대하다고 생각할 수 있고, 누군가는 1MB 정도가 거대하다고 생각할 수 있습니다.
JVM 세상에서 거대한 객체로 인식되는 것은 GC와 연관 있기 때문에 GC에 대해서도 알아보겠습니다.
JVM GC - G1GC
https://taes-k.github.io/2021/09/05/g1gc-detail/ JDK 11부터는 default GC가 G1GC입니다.
G1GC의 경우 Heap이 동일한 크기의 여러 지역으로 분할되어 있는 것이 특징입니다.
각 지역은 Eden, Survior, Tenured로 분류되며 새로운 객체가 생성되면 Eden으로 할당됩니다.
이후 GC 사이클에서 한 번 이상 살아남은 객체는 Survior로 이동하고, 충분히 GC 사이클에서 살아남으면 Tenured 지역으로 이동됩니다.
이때 한 가지 예외로 객체가 거대한 객체로 분류되는 경우에는 바로 Tenured 지역으로 할당됩니다.
거대한 객체의 기준
G1GC에서 지역의 메모리 영역 50%보다 큰 모든 객체를 거대한 객체로 간주합니다.
만약 거대한 객체가 한 영역보다 작으면 전체 영역을 차지하고, N개의 영역보다 크고 N+1 개의 영역보다 작으면 N+1개의 영역을 차지합니다.
예를 들어 32MB 지역을 가진다면 객체가 16MB가 넘는 경우 거대한 객체로 분류됩니다.
G1GC의 하나의 메모리 영역은 -XX:G1HeapRegionSize의 옵션으로 설정될 수 있으며 기본적으로는 최대 Heap 사이즈의 1/2048 만큼의 계산된 사이즈를 가집니다.
만약 옵션을 주어 설정한다면 1 ~ 32MB 정도로 설정할 수 있으며 2의 거듭제곱 값으로 주어야 합니다.
G1HeapRegionSize 확인 방법
jcmd란 JVM 프로세스의 상태를 진단하고 모니터링하기 위한 도구입니다.
jcmd 명령어를 통하여 PID를 탐색하고 VM.flags (현재 설정된 옵션 목록 출력)을 통하여 G1 HeapRegionSize크기를 확인해 볼 수 있습니다.
거대한 객체가 Java Heap에서 가지는 의미
GC가 발생하게 되면 활용하지 않는 영역은 제거하고, 각 객체들을 영역별로 옮기는 과정에서 조각 모음의 역할도 수행합니다.
단, 거대한 객체의 경우 회수되기 전까지 잉여 공간을 활용할 수 없어 메모리 파편화가 발생하고, 공간이 충분한데도 메모리가 부족하여 OOM이 발생할 수 있습니다.
또한 Minor GC의 경우 Eden 영역의 객체를 Survivor 영역으로 이동시키며 속도가 수십 ms 정도로 빠릅니다. (Survivor 영역에서 오래 살아남은 객체를 Tenured 영역으로 승격시키기도 합니다)
하지만 거대한 객체는 Tenured 영역으로 바로 할당되므로 Full GC가 발생할 가능성을 증가시킵니다.
Full GC의 경우 수백ms 에서 수초가 수행될 수 있어서 애플리케이션의 응답속도가 느려질 수 있게 됩니다.
거대한 객체가 탐지되었을 때 대응 방법
1. 데이터를 Chunking 할 수 있다면 여러 개의 작은 List로 분할해 볼 수 있습니다.
2. Snappy, LZ4, GZIP 등을 활용하여 압축을 활용해볼 수 있습니다. (단, 압축으로 인하여 CPU 오버헤드가 생길 수 있습니다)
3. -XX:G1HeapRegionSize 옵션을 통해 Region 크기를 증가시켜 거대한 객체로 포함되는 기준을 높일 수 있습니다.
참고자료
https://devblogs.microsoft.com/java/whats-the-deal-with-humongous-objects-in-java/
https://johngrib.github.io/wiki/java/gc/g1gc/#humongous-object
'Java > 자바를 더 깊게' 카테고리의 다른 글
JVM Warm-up 이란 (0) 2023.09.09 자바 Inner static class 로딩 시점 (0) 2022.04.10 StringBuilder의 초기화 방법 (0) 2022.03.12 [Java] Java Multi-Thread Programming의 모든것을 알아보자 (0) 2022.03.02 [Java] Java Collection Framework의 모든것을 알아보자 (0) 2022.02.22