자바 가비지 컬렉션(GC, Garbage Collection) 기본 개념
가비지 컬렉션(GC, Garbage Collection)이란?
자바 가상 머신(JVM)에 의해 구동되는 자바 프로그램은 메모리 관리를 개발자가 직접 명시적으로 수행하지 않고 자동 메모리 관리 기능을 지원한다. 가비지 컬렉션은 자바의 메모리 관리 방법 중의 하나로 자바 가상 머신의 Heap 영역에서 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객체를 모아 주기적으로 제거하는 프로세스를 말한다.
두-두 등장 배경
과거의 프로그래밍 언어들은 메모리 할당기능이 존재하지 않거나 프로그래머가 할당한 뒤 수동으로 해제까지 하는 방식으로 메모리를 관리하였다. 대표적인 예가 C와 C++이다. 두 언어에서는 OS 레벨의 메모리에 직접 접근하기 때문에 free()라는 메소드를 호출하여 할당받았던 메모리를 명시적으로 해제해주어야 했다.
그러나 이런 방식은 아래와 같은 실수들로 인해 버그의 원인이 되곤 하였다. 게다가 일반적으로 버그는 재현이 가능하고 오류가 있는 부분으로부터 가까운 곳에서 발생해야 파악하기 쉬운데, 메모리 관련 버그는 한참 떨어진 곳에서 발생하고 재현까지 어려운 경우가 허다했다고 한다.
- 이중 해제: 해제했던 메모리를 실수로 재해제
- 유효하지 않은 포인터 접근: 해제했던 메모리를 실수로 재사용
- 메모리 누수(Memory Leak): 메모리를 할당한 후 필요 없어진 뒤에도 해제를 하지 않아 메모리 누수 발생하고 이러한 누수가 쌓여 프로그램 종료까지 이어질 수 있음
반면 Java에서는 가비지 컬렉터가 메모리 관리를 대행해 주기 때문에 Java 프로세스가 한정된 메모리를 효율적으로 사용할 수 있게 하고, 개발자 입장에서 메모리 관리, 메모리 누수(Memory Leak) 문제에서 대해 관리하지 않아도 되어 개발에만 집중할 수 있다는 장점이 있다.
가비지 컬렉션이라는 개념은 자바의 대표적인 개념으로 유명하지만 자바에서 처음 사용된 개념은 아니다. 1959년에 존 매카시라는 인물이 LISP라는 함수형 언어의 메모리 관리를 위해 처음 만들었다고 한다. 물론 자바가 가비지 컬렉션이라는 개념을 더욱 대중화시킨데 기여한 부분은 분명히 있다.
자바에서 의미하는 가비지(Garbage)란?
가비지 켈렉션이 가비지를 정리해 주는 기능을 한다고 하고 가비지는 쓰레기를 의미한다. 그렇다면 자바에서 의미하는 쓰레기가 무엇일까. 일반적으로 Heap 영역에서 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객체를 가비지(Garbage)라고 한다. 흔히 작성하는 코드를 통해 쉽게 이해할 수 있다.
Student std = new Student("김민수");
std.goSchool();
// 가비지 발생
std = new Student("이영희");
위 코드를 바탕으로 아래 그림을 보면 조금 더 명확하게 이해할 수 있다.
코드의 첫 번째 줄에서 "김민수"라는 이름을 가진 Student 객체를 생성하고 std 변수가 해당 객체를 참조하게 하였다.
그러나 마지막 줄에서 "이영희"라는 이름을 가진 Student 객체를 다시 한번 생성하였고 std 변수가 이 객체를 참조하게 하였다. 이 과정에서 기존에 "김민수"로 생성된 Student 객체는 더 이상 참조되지 않고 사용이 되지 않아 가비지(Garbage)가 된다.
조금 더 극단적인 예로 아래 코드를 살펴보자.
for (int i = 0; i < 1000; i++) {
TestObject obj = new TestObject();
obj.doSomething();
}
반복문에 의해 1000건의 TestObject 객체가 For문의 스코프 내에서 생성되고 사용되지만 루프가 끝나고 루프 밖에서는 더 이상 사용할 일이 없고 이 객체들은 메모리 내의 가비지가 된다.
가비지 판단 방법
가비지 컬렉션은 특정 객체가 가비지인지 아닌지 판단하기 위해서 도달성 즉, 도달능력(Reachability)이라는 개념을 적용한다. 객체에 대해 레퍼런스가 있다면 Reachable로 구분되고, 객체에 유효한 레퍼런스가 없다면 Unreachable로 구분해 버리고 수거해 버린다
- Reachable: 객체가 참조되고 있는 상태
- Unreachable : 객체가 참조되고 있지 않은 상태 (GC의 대상)
자바 가상 머신 메모리에서는 객체들은 실질적으로 Heap영역에만 생성되고 Method Area 영역과 Stack에서는 Heap 영역에 생성된 객체의 주소만을 참조하는 형식으로 구성된다. 하지만 Heap 영역에 객체들이 메서드가 끝나는 등의 특정 이벤트들로 인하여 Heap 영역 객체의 메모리 주소를 가지고 있는 참조 변수가 삭제되는 현상이 발생하면 위 그림에서 Object 3처럼 어디에서도 참조하고 있지 않은 객체(Unreachable)가 발생하게 된다. 이러한 객체들을 주기적으로 가비지 컬렉션이 제거해 주는 것이다.
그럼 가비지 컬렉션 완전 좋은 거 아닌가?!
가비지 컬렉션을 이용하면 개발자가 동적으로 할당한 메모리 영역 전체를 완벽하게 관리하지 않아도 되고 불필요한 객체들을 주기적으로 제거함으로써 한정된 메모리를 효율적으로 사용할 수 있게 해 준다
아주 필수적이고 만능 같은 기능이지만 모든 것에 장단점이 있듯이 가비지 컬렉션도 단점이 존재한다.
- 어떤 메모리를 해제해야 할지 결정하는 데 사용되는 알고리즘에 의해 비용이 든다.
- 가비지 컬렉션이 행동하는 타이밍이나 GC의 점유 시간을 사전에 예측하기 어려워 제어가 어렵다.
- 할당된 메모리가 해제되는 시점을 알 수 없게 된다.
- 가비지 컬렉션이 동작하는 동안에는 다른 동작을 멈추기 때문에 오버헤드가 발생되는 문제점이 있다.
(전문적인 용어로 Stop-The-World라고 한다.)
💡 STW (Stop The World)
가비지 컬렉션을 수행하기 위해 자바 가상 머신이 프로그램 실행을 멈추는 현상을 의미한다.
가비지 컬렉션이 작동하는 동안 가비지 컬렉션에 관련된 스레드를 제외한 모든 스레드는 멈추게 되어 서비스 이용에 차질이 생길 수 있다. 따라서 이 시간을 최소화시키는 것이 쟁점이다.
위와 같은 문제로 인해 가비지 컬렉션이 너무 자주 실행되면 소프트웨어 성능 하락의 원인이 되기도 한다. 따라서 애플리케이션의 사용성을 유지하면서 효율적이게 GC를 실행하는 최적화 작업이 개발자의 숙제가 된다. 그리고 이러한 GC 최적화 작업을 GC 튜닝이라고 한다. (예를 들면 익스플로러는 이 가비지 컬렉션을 너무 자주 실행하여 성능 문제를 일으키는 것으로 악명이 높았다.)
추가로 실시간성이 매우 강조되는 프로그램일 경우 가비지 컬렉션에게 메모리를 맞기는 것은 맞지 않을 수 있다. 실시간 시스템에서 가비지 컬렉션이 사용된다면 치명적인 오류를 발생할 수 있다. 특히나 군사목적의 프로그래밍(미사일 등) 혹은 비행 시스템 등에서 실시간으로 목표물 지점으로 날아가고 있는 중간에 가비지 컬렉션이 발생하여 동작하게 되면 알고리즘 동작이 멈출 수 있는 가능성 때문에 실시간 시스템에서는 가비지 컬렉션을 지양해야 한다.
자바 가비지 컬렉션(GC) 동작방식
가비지 컬렉션의 청소 방법 - Mark And Sweep
가비지 컬렉션은 Unreachable 한 객체를 청소하기 위해 Mark-Sweep 알고리즘을 사용한다. Mark-Sweep 이란 다양한 다양한 가비지 컬렉션에서 사용되는 객체를 솎아내는 내부 알고리즘이다. 가비지 컬렉션이 동작하는 아주 기초적인 청소 과정이다.
원리는 그림을 보면 쉽게 이해할 수 있다. 가비지 컬렉션이 될 대상 객체를 식별(Mark)하고 제거(Sweep)하며 객체가 제거되어 단편화된 메모리 영역을 앞에서부터 채워나가는 작업(Compaction)을 수행하게 된다.
- Mark: 사용되는 메모리(Reachable)와 사용되지 않는 메모리(Unreachable)를 식별하는 작업이다.
Root Space로부터 그래프 순회를 통해 연결된 객체들을 찾아내 각각 어떤 객체를 참조하고 있는지 찾아서 마킹한다. - Sweep: Mark 단계에서 사용되지 않음(Unreachable)으로 식별된 메모리를 해제하는 작업이다.
참조하고 있지 않은 객체 즉 Unreachable 객체들을 Heap에서 제거한다. - Compaction: Sweep 후에 분산된 객체들을 Heap의 시작 주소로 모아 압축한다.
(가비지 컬렉션 종류에 따라 생략되는 경우도 있다.)
이렇게 Mark And Sweep 방식을 사용하면 루트로부터 연결이 끊긴 객체들을 모두 지울 수 있다.
💡 가비지 컬렉션의 Root Space
Mark And Sweep 방식은 루트로부터 해당 객체에 접근이 가능한지가 해제의 기준이 된다.
자바의 가비지 컬렉션에서의 Root Space는 Heap 메모리 영역을 참조하는 Method area, Stack, Native method stack이 되게 된다.
합(Heap) 메모리 구조
자바 가상 머신의 힙 영역은 JVM이 관리하는 프로그램 상에서 데이터를 저장하기 위해 런타임 동적으로 할당하여 사용하는 영역으로 가비지 컬렉션의 대상이 되는 공간이다. 이 공간은 2가지 전제를 가지고 처음 설계되었다.
- 대부분의 객체는 금방 접근 불가능한 상태(Unreachable)가 된다.
- 오래된 객체에서 새로운 객체로의 참조는 아주 적게 존재한다.
간단히 말하면 객체는 대부분 일회성이며 메모리에 오랫동안 남아있는 경우는 드물다는 것이다.
이러한 특성을 이용해 개발자들은 보다 효율적인 메모리 관리를 위해, 객체의 생존 기간에 따라 물리적인 Heap 영역을 나누게 되었고 Young과 Old 총 2가지 영역으로 설계하였다.
[ Young 영역(Young Generation) ]
- 새롭게 생성된 객체가 할당(Allocation)되는 영역이다.
- 대부분의 객체가 금방 Unreachable 상태가 되기 때문에, 많은 객체가 Young 영역에 생성되었다가 사라진다.
- Young 영역에 대한 가비지 컬렉션(Garbage Collection)을 Minor GC라고 부른다.
[ Old 영역(Old Generation) ]
- Young영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역이다.
- Young 영역보다 크게 할당되며, 영역의 크기가 큰 만큼 가비지는 적게 발생한다.
- Old 영역에 대한 가비지 컬렉션(Garbage Collection)을 Major GC 또는 Full GC라고 부른다.
그림에서 알 수 있듯이 Old 영역이 Young 영역보다 크게 할당되는 이유는 Young 영역의 수명이 짧은 객체들은 큰 공간을 필요로 하지 않으며 큰 객체들은 Young 영역이 아니라 바로 Old 영역에 할당되기 때문이다.
💡 카드 테이블 (Card Table)
예외적인 상황으로 Old 영역에 있는 객체가 Young 영역의 객체를 참조하는 경우도 존재할 것이다. 이러한 경우를 대비하여 Old 영역에는 512 bytes의 덩어리(Chunk)로 되어 있는 카드 테이블(Card Table)이 존재한다. 카드 테이블에는 Old 영역에 있는 객체가 Young 영역의 객체를 참조할 때마다 그에 대한 정보가 표시된다.
카드 테이블이 도입된 이유는 Young 영역에서 가비지 컬렉션(Minor GC)이 실행될 때 모든 Old 영역에 존재하는 객체를 검사하여 참조되지 않는 Young 영역의 객체를 식별하는 것이 비효율적이기 때문이다. 그래서 Young 영역에서 가비지 컬렉션이 진행될 때 카드 테이블만 조회하여 GC의 대상인지 식별할 수 있도록 하고 있다.
💡 Java8에서의 Permanent의 행방은?
Permanent는 직역하면 영구적인 세대의 의미로서, 생성된 객체들의 정보의 주소값이 저장된 공간이다.
Perm 영역은 보통 Class의 Meta 정보나 Method의 Meta 정보, Static 변수와 상수 정보들이 저장되는 공간으로 흔히 메타데이터 저장 영역이라고도 한다. 이 영역은 Java 8부터는 Native 영역으로 이동하여 Metaspace 영역으로 변경되었다. 다만 기존 Perm 영역에 존재하던 Static Object는 Heap 영역으로 옮겨져서 GC의 대상이 최대한 될 수 있도록 하였다
힙 영역은 더욱 효율적인 가비지 컬렉션을 위해 또다시 Young 영역을 3가지 영역(Eden, Survivor 0, Survivor 1)으로 나누고 이를 통해 객체의 생존 기간을 면밀하게 제어하여 가비지 컬렉션이 보다 정확하게 불필요한 객체를 제거할 수 있도록 한다.
[ Eden ]
- new를 통해 새로 생성된 객체가 위치한다.
- 정기적인 쓰레기 수집 후 살아남은 객체들은 Survivor 영역으로 보낸다.
[ Survivor 0 / Survivor 1 ]
- 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역이다.
- Survivor 영역에는 특별한 규칙이 있는데, Survivor 0 또는 Survivor 1 둘 중 하나에는 꼭 비어 있어야 하는 것이다.
힙 영역을 제외한 자바의 다른 메모리 구조도 궁금한 경우 아래 포스트 참고 바랍니다:)
Minor GC 과정
Young 영역은 짧게 살아남는 메모리들이 존재하는 공간으로 모든 객체는 처음에는 Young 영역에 생성되게 된다.
Young 영역의 간은 Old 영역에 비해 상대적으로 작기 때문에 메모리 상의 객체를 찾아 제거하는데 적은 시간이 걸리고 이 때문에 Young Generation 영역에서 발생되는 GC를 Minor GC라고 부른다.
Minor GC의 과정은 아래와 같다.
- 새로 생성된 객체가 Eden 영역에 할당된다.
- 객체가 계속 생성되어 Eden 영역이 꽉 차게 되고 Minor GC가 실행된다.
- Eden 영역에서 살아남은 객체는 1개의 Survivor 영역으로 이동된다.
- Eden 영역에서 사용되지 않는 객체의 메모리가 해제된다.
- 1~2번의 과정을 반복하고 Survivor 0과 Survivor1을 왔다 갔다 한다.
(1개의 Survivor 영역은 반드시 빈 상태가 된다.) - 이러한 과정을 반복하여 계속해서 살아남은 객체는 Old 영역으로 이동(Promotion)된다.
그림으로 보면 아래와 같다.
1. 처음 생성된 객체는 Young 영역의 일부인 Eden 영역에 위치한다.
2. 객체가 계속 생성되어 Eden 영역이 꽉 차게 되고 Minor GC가 실행된다.
3. Mark 동작을 통해 reachable 객체를 탐색한다.
4. Eden 영역에서 살아남은 객체는 1개의 Survivor 영역으로 이동한다.
5. Eden 영역에서 사용되지 않는 객체(unreachable)의 메모리를 해제(sweep)한다.
6. 살아남은 모든 객체들은 age값이 1씩 증가
7. 또다시 Eden 영역에 신규 객체들로 가득 차게 되면 다시 한번 Minor GC 발생하고 Mark 한다
8. Marking 한 객체들을 비어있는 Survival 1으로 이동하고 sweep
9. 다시 살아남은 모든 객체들은 age가 1씩 증가
10. 위 과정을 반복
💡 Age 값이란?
Survivor 영역에서 객체의 객체가 살아남은 횟수를 의미하는 값이며, Object Header에 기록된다. 만일 age 값이 임계값에 다다르면 Promotion(Old 영역으로 이동) 여부를 결정한다. JVM 중 가장 일반적인 HotSpot JVM의 경우 이 age의 기본 임계값은 31이다. 객체 헤더에 age를 기록하는 부분이 6 bit로 되어있기 때문이다.
또한 Survivor 영역의 제한 조건으로 Survivor 영역 중 반드시 1개는 사용되어야 하고, 나머지는 비어 있어야 한다. 만약 두 Survivor 영역에 모두 데이터가 존재하거나, 모두 사용량이 0이라면 현재 시스템이 정상적인 상황이 아니라는 반증이 된다.
Major GC 과정
Old 영역은 길게 살아남는 메모리들이 존재하는 공간이다. Old 영역의 객체들은 거슬러 올라가면 처음에는 Young 영역에 의해 시작되었으나, GC 과정 중에 제거되지 않은 경우 age 임계값이 차게 되어 이동된 녀석들이다. 그리고 Major GC는 객체들이 계속 Promotion 되어 Old 영역의 메모리가 부족해지면 발생하게 되고 Full GC라고도 불린다.
Promotion 과정을 살펴보면 아래와 같다.
1. 객체의 age가 임계값(여기선 9로 설정)에 도달하는 경우가 발생한다.
2. 해당 객체들 Old 영역으로 이동된다. 이를 Promotion이라 부른다.
3. 위의 과정이 반복되어 Old 영역의 공간(메모리)이 부족하게 되면 Major GC가 발생되게 된다.
Major GC는 Old 영역이 가득 차면 GC를 실행하는 단순한 방식이다. Old 영역에 할당된 메모리가 허용치를 넘게 되면, Old 영역에 있는 모든 객체들을 검사하여 참조되지 않는 객체들을 한꺼번에 삭제하는 Major GC가 실행되게 된다. 하지만 Old 영역은 Young 영역에 비해 상대적으로 큰 공간을 가지고 있어, 이 공간에서 메모리 상의 객체 제거에 많은 시간이 걸리게 된다.
예를 들어 Young 영역은 일반적으로 Old 영역보다 크기가 작기 때문에 GC가 보통 0.5초에서 1초 사이에 끝난다. 그렇기 때문에 Minor GC는 애플리케이션에 크게 영향을 주지 않는다. 하지만 Old 영역의 Major GC는 일반적으로 Minor GC보다 시간이 오래 걸리며, 10배 이상의 시간을 사용한다. 바로 여기서 본문 초반에 소개했던 Stop-The-World 문제가 발생하게 된다. 아래 표는 Minor GC와 Major GC를 간략하게 비교한 표이다.
Major GC가 일어나면 Thread가 멈추고 Mark and Sweep 작업을 해야 해서 CPU에 부하를 주기 때문에 멈추거나 버벅거리는 현상이 일어나기 때문이다. 따라서 자바 개발자들은 끊임없이 가비지 컬렉션 알고리즘을 발전시켜왔다.
다양한 자바 가비지 컬렉션 알고리즘
Serical GC
# Serial GC 실행 명령어
# -XX:+UseSerialGC: Serial GC 알고리즘으로 힙 메모리를 관리하도록 실행
java -XX:+UseSerialGC -jar Application.java
- Java SE 5, 6에서 사용되는 디폴트 가비지 컬렉션이다.
- 서버의 CPU 코어가 1개일 때 사용하기 위해 개발된 가장 단순한 GC이다.
- GC를 처리하는 스레드가 1개 (싱글 스레드)여서 가장 stop-the-world 시간이 길다
- Minor GC 에는 Mark-Sweep을 사용하고, Major GC에는 Mark-Sweep-Compact를 사용한다.
- 보통 실무에서 사용하는 경우는 없다. (디바이스 성능이 안 좋아서 CPU 코어가 1개인 경우에만 사용)
Parallel GC
# GC 스레드는 기본적으로 cpu 개수만큼 할당
# 옵션을 통해 GC를 수행할 쓰레드의 갯수 등을 설정 가능
java -XX:+UseParallelGC -jar Application.java
# -XX:ParallelGCThreads=N : 사용할 쓰레드의 갯수
- Java 8의 디폴트 GC이다.
- Serial GC와 기본적인 알고리즘은 같지만 Young 영역의 Minor GC를 멀티 스레드로 수행한다.
(Old 영역은 여전히 싱글 스레드) - Serial GC에 비해 stop-the-world 시간 감소된다.
Parallel Old GC (Parallel Compacting Collector)
java -XX:+UseParallelOldGC -jar Application.java
# -XX:ParallelGCThreads=N : 사용할 쓰레드의 갯수
- Parallel GC에서 Ol 영역에 새로운 알고리즘을 추가한 버전이다.
- Young 영역뿐만 아니라, Old 영역에서도 멀티 스레드로 GC를 수행한다.
- 새로운 가비지 컬렉션 청소 방식인 Mark-Summary-Compact 방식을 이용한다.
CMS GC (Concurrent Mark Sweep)
java -XX:+UseConcMarkSweepGC -jar Application.java
- 애플리케이션의 스레드와 GC 스레드가 동시에 실행되어 stop-the-world 시간을 최대한 줄이기 위해 고안된 GC이다.
- GC 대상을 파악하는 과정이 복잡한 여러 단계로 수행되기 때문에 다른 GC 대비 CPU 사용량이 높다.
- 메모리 파편화 문제가 있다.
- CMS GC는 Java9 버전부터 deprecated 되었고 결국 Java14에서는 사용이 중지되었다.
G1 GC (Garbage First)
java -XX:+UseG1GC -jar Application.java
- CMS GC를 대체하기 위해 jdk 7 버전에서 최초로 release 된 GC로 Java 9+ 버전의 기본 GC로 지정되었다.
- 4GB 이상의 힙 메모리, Stop the World 시간이 0.5초 정도 필요한 상황에 사용 (Heap이 너무 작을 경우 미사용 권장)
- Region이라는 새로운 개념 도입하였다.
기존의 GC 알고리즘에서는 Heap 영역을 물리적으로 고정된 Young / Old 영역으로 나누어 사용하였지만,
G1 GC는 전체 힙 영역을 Region이라는 영역으로 체스판과 같이 분할하여 상황에 따라 Eden, Survivor, Old 등 역할을 고정이 아닌 동적으로 부여한다. 가비지로 가득 찬 영역을 빠르게 회수하여 빈 공간을 확보하므로, 결국 GC 빈도가 줄어드는 효과를 얻게 되는 원리이다.
Java 9+부터 기본 GC로 자리 잡은 G1 GC에서는 이전의 GC들처럼 일일이 메모리를 탐색해 객체들을 제거하지 않는다. 대신 메모리가 많이 차있는 영역(region)을 인식하는 기능을 통해 메모리가 많이 차있는 영역을 우선적으로 GC 한다. 즉, G1 GC는 Heap Memory 전체를 탐색하는 것이 아닌 영역(region)을 나눠 탐색하고 영역(region) 별로 GC가 일어난다.
또한 이전의 GC 들은 Young Generation에 있는 객체들이 GC가 돌 때마다 살아남으면 Eden → Survivor0 → Survivor1으로 순차적으로 이동했지만, G1 GC에서는 순차적으로 이동하지는 않는다. 대신 G1 GC는 더욱 효율적이라고 생각하는 위치로 객체를 Reallocate(재할당) 시킨다. 예를 들어 Survivor1 영역에 있는 객체가 Eden 영역으로 할당하는 것이 더 효율이라라고 판단될 경우 Eden 영역으로 이동시킨다.
Shenandoah GC
java -XX:+UseShenandoahGC -jar Application.java
- Java 12에 release 되었다.
- 레드 햇에서 개발한 GC로 큰 GC 작업을 적은 횟수로 수행하는 것보다 작은 GC 작업을 여러분 수행하는 게 더 좋다'는 개념을 적용해 만들어진 GC이다.
- 기존 CMS가 가진 단편화, G1이 가진 pause의 이슈를 해결하였다.
- 강력한 Concurrency와 가벼운 GC 로직으로 heap 사이즈에 영향을 받지 않고 일정한 pause 시간이 소요가 특징이다.
ZGC (Z Garbage Collector)
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -jar Application.java
- Java 15에 release 되었다.
- 대량의 메모리(8MB ~ 16TB)를 low-latency로 잘 처리하기 위해 디자인된 GC이다.
- G1의 Region처럼 ZGC는 ZPage라는 영역을 사용하며, G1의 Region은 크기가 고정인데 비해, ZPage는 2mb 배수로 동적으로 운영된다. (큰 객체가 들어오면 2^ 로 영역을 구성해서 처리한다.)
- ZGC가 내세우는 최대 장점 중 하나는 힙 크기가 증가하더도 'stop-the-world'의 시간이 절대 10ms를 넘지 않는다는 것이다.
글을 마치며
으악 GC! 간단한 개념정도는 알고 있었는데 자세히 까보고 알고리즘별로 살펴보니 너무 어렵다. 이걸 당장 다 기본적으로 알고 있기는 어려울 것 같고 내 머릿속에 덧칠한다는 느낌으로 쭉 살펴봤다. 헷갈릴 때마다 꺼내봐야겠다. 다음 자바 버전에서는 또 어떤 GC 알고리즘이 나올지 기대된다. 세상의 천재들은 많고 그들의 생각을 엿볼 수 있다는 건 꽤나 흥미로운 것 같다.
참고 자료 및 사이트
- https://mangkyu.tistory.com/118
- https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98GC-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%F0%9F%92%AF-%EC%B4%9D%EC%A0%95%EB%A6%AC#%EA%B0%80%EB%B9%84%EC%A7%80_%EC%BB%AC%EB%A0%89%EC%85%98_%EC%B2%AD%EC%86%8C_%EB%B0%A9%EC%8B%9D
- https://jaemunbro.medium.com/java-metaspace%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-ac363816d35e
- https://yaboong.github.io/java/2018/06/09/java-garbage-collection/