-
[JVM] 가비지 컬렉터와 메모리 할당 전략 - 메모리 할당과 회수 전략DevBook/JVM 밑바닥까지 파헤치기 2025. 3. 27. 22:27
- JVM이 제공하는 자동 메모리 관리의 근본적인 목표는 객체의 메모리를 '자동으로 할당'하고 객체에 할당된 메모리를 '자동으로 회수'하는 것
- 객체 메모리 할당이란 개념적으로는 힙에 할당한다는 뜻
- 참고)
- 객체 할당 규칙은 고정된 게 아님
- 현재 사용하는 가비지 컬렉터와 메모리 관련 가상 머신 매개 변수 설정값에 따라 달라질 수 있음
여기서는 시리얼 컬렉터를 사용한 가장 기본적인 메모리 할당 정책을 알아본다.
(모든 상황에서 최고인 단 하나의 컬렉터나 매개 변수 조합이란 없다)
1. 객체는 먼저 에덴에 할당된다.
- 대부분의 경우 객체는 신세대의 Eden 영역에 할당됨
- Eden 영역의 공간이 부족해지면 가상 머신은 Minor GC를 시작함
- Eden과 현재 사용중인 Survivor 영역(from)에 있는 객체 중 살아남은 객체들을 다른 Survivor 영역(to)으로 복사함
- mark-copy 알고리즘 사용
- Survivor 공간이 부족할 경우 할당 보증 메커니즘을 발동해 곧바로 구세대로 옮김
- 복사 후 객체의 age(생존 횟수) 증가
- 일정 age 이상이면 이후 GC 때 구세대로 승격됨
- 구세대로 승격된 후에는 객체의 age 값은 더 이상 카운트되지 않음
- GC 후, Survivor 영역의 from/to 역할이 바뀜 (다음 GC 때는 현재 to가 from이 됨)
Q. 할당 보증(Allocation Guarantee) 메커니즘이란?
더보기- JVM이 Minor GC 수행하기 전에 구세대에 객체를 안전하게 승격시킬 수 있는 충분한 공간이 있는지 확인하는 메커니즘
- 만약 해당 공간이 보장되지 않으면, Minor GC 대신 Full GC가 발생할 수 있음
- 동작 방식 요약
- 에덴 공간이 가득차서 Minor GC가 필요함
- JVM이 할당 보증 메커니즘 수행함
- 이번 GC에서 구세대로 승격될 객체가 얼마나 되는지 확인
- 구세대에 그만큼의 여유 공간이 있는지 확인
- 만약 없다면, Minor GC가 아닌 Full GC 실행 (신세대, 구세대 모두 정리)
- 있다면 그대로 Minor GC 수행
*2~4는 구세대로 객체가 승격되는 조건을 이야기함
2. 큰 객체는 곧바로 구세대에 할당된다.
- 큰 객체란 커다란 '연속된' 메모리 공간을 필요로 하는 자바 객체
- ex) 매우 긴 문자열이나 원소가 매우 많은 배열
- 큰 객체들을 담기 위한 '연속된' 공간을 확보하기 위해 수많은 다른 객체를 옮겨야 하므로 심각한 메모리 복사 오버헤드를 동반함
- -XX:PretenureSizeThreshold 매개 변수를 설정하면 설정값보다 큰 객체를 곧바로 구세대에 할당함
- 해당 매개 변수의 목적은 에덴과 두 생존자 공간 사이의 대규모 복사를 줄이는 데 있음
- 해당 매개 변수는 시리얼과 파뉴 신세대 컬렉터에만 적용됨 (PS 같은 다른 신세대 컬렉터들은 이 매개 변수를 지원하지 않음)
3. 나이가 차면 구세대로 옮겨진다.
- 핫스팟 가상 머신의 컬렉터 대부분은 힙 메모리 관리에 '세대 단위 컬렉션'을 활용함
- 각 객체의 객체 헤더에 세대 나이 카운터를 두도록 함
- 객체는 주로 에덴에 할당된다. (큰 객체는 조건에 따라 구세대로 할당될 수 있음)
- 처음 할당되었을 때의 나이는 0이다.
- 첫 번째 Minor GC에서 살아남은 객체는, 생존자 공간이 충분하면 생존자 공간으로 옮겨지면서 나이가 1 증가한다.
- 생존자 공간에서 Minor GC 겪을 때마다 다시 1씩 증가한다.
- 특정 나이가 되면 구세대로 승격된다.
- 구세대로 승격되는 나이는 -XX:MaxTenuringThreshold 매개 변수로 정함
4. 공간이 비좁으면 강제로 승격시킨다.
- '생존자 공간 점유율' 조건으로 인해 객체의 나이가 -XX:MaxTenuringThreshold보다 적어도 구세대로 승격될 수 있음
- 기본값은 50%로, 생존 객체 전체의 크기 총합이 (복사할) 생존자 공간의 절반을 넘어서면 모든 객체를 구세대로 옮김
- 이때 -XX:MaxTenuringThreshold로 정한 나이는 무시됨
'DevBook > JVM 밑바닥까지 파헤치기' 카테고리의 다른 글
[JVM] 가상 머신 실행 서브시스템 (2) - 클래스 로딩 메커니즘 (0) 2025.04.01 [JVM] 가상 머신 실행 서브시스템 (1) - 클래스 파일 구조 (0) 2025.03.29 [JVM] 가비지 컬렉터와 메모리 할당 전략 (2) - 클래식 가비지 컬렉터 > G1 GC (0) 2025.03.18 [JVM] 가비지 컬렉터와 메모리 할당 전략 (2) - 클래식 가비지 컬렉터 (0) 2025.03.18 [JVM] 가비지 컬렉터와 메모리 할당 전략 (1) - 기본 알고리즘 (0) 2025.03.17