Garbage Collection이란?
Garbage Collection이란 메모리 관리 기법 중의 하나로, 프로그램이 동적으로 할당했던 메모리 영역 중에서 필요 없게 된 영역을 해제하는 것이다.
JVM 메모리 구조
GC의 종류를 살펴보기 전에 JVM 메모리 구조를 먼저 알아보자. JVM의 메모리 구조는 크게 Heap / Perm / Thread로 나눌 수 있다. Heap은 다시 Young(New) 영약과 Old 영역으로, Young 영역은 다시 Eden / Survivor1 / Survivor2로 나눌 수 있다. Young 영역은 객체가 처음 생성 시 저장되는 영역을 나타낸다. 정확히는 new 연산자를 통해 생성되는 객체들은 Eden 영역에 저장된다. Old 영역은 Young 영역에 존재하던 객체들이 오래되어 저장되는 영역이다. Perm 영역은 Class 혹은 Method 코드가 저장되는 영역이다. 하지만 Java 8 이상부터는 Perm 영역이 사라지고 Metaspace가 등장했다. 아래 그림은 Java 7까지의 메모리 구조를 나타낸다.

Garbage Collection의 종류와 동작 방식
Java의 GC는 크게 Minor GC와 Full GC로 나눌 수 있다. Minor GC는 Young 영역에서 발생하는 GC이고, Full GC는 Old 영역에서 발생하는 GC이다.
Minor GC
Minor GC는 다음과 같은 순서로 동작한다.
- 최초 Minor GC가 발생하기 전에 할당되어 있던 객체들은 Eden 영역에만 존재한다.
- 최초 Minor GC가 발생하면 Eden 영역 중 활성 객체가 Survivor1 영역으로 이동하고 비활성 객체만 남은 Eden 영역은 Clear 된다.
- 다음 Minor GC가 발생하면 이미 살아남은 객체가 존재하는 Survivor1 영역으로 객체가 계속 쌓인다.
- Survivor1 영역이 가득 차게 되면 그중에서 활성 객체들을 Survivor2 영역으로 이동시키고, Survivor1 영역은 Clear 된다.
- 이후 위 작업이 Survivor1 영역과 Survivor2 영역을 번갈아가면서 수행되고, 계속해서 활성 객체로 생존하는 객체들은 시간이 지남에 따라 Old 영역으로 이동한다.
위의 과정을 그림으로 살펴보면 다음과 같다. 이 절차를 확인해보면 알겠지만 Survivor 영역 중 하나는 반드시 비어 있는 상태로 남아 있어야 한다.

Full GC
Full GC는 Old 영역이 Full이 되면 수행된다. Full GC는 Old 영역을 스캔하여 객체들의 참조 상태를 표시하고, 참조되지 않는 객체를 해제(Mark & Compact)하는 작업을 실행한다. Young 영역은 일반적으로 Old 영역에 비해 크기가 작기 때문에 Minor GC가 0.5초에서 1초 사이에 끝난다. 하지만 Old 영역은 크기도 크고, Young 영역을 참조할 수도 있기 때문에 Minor GC에 비해 Full GC는 10배 이상의 시간을 사용한다. 따라서 Full GC는 프로그램의 성능에 아주 큰 영향을 끼친다.
Garbage Collection의 장점
GC에는 다음과 같은 장점이 있다.
- 프로그래머가 동적으로 할당한 메모리 영역을 관리할 필요가 없어진다.
- 유효하지 않은 포인터에 접근하는 오류를 막을 수 있다.
- 이미 해제된 메모리를 다시 해제하는 오류를 막을 수 있다.
- 더는 필요하지 않은 메모리가 해제되지 않고 남아 있는 오류(메모리 누수)를 막을 수 있다.
Garbage Collection의 단점
GC에는 다음과 같은 단점이 있다.
- 어떤 메모리를 해제할지 결정하는데 비용이 든다.
- GC 알고리즘이 메모리 해제 시점을 추적해야 하므로 오버헤드가 발생한다.
- GC가 일어나는 타이밍이나 점유 시간을 예측하기 어렵다.
- 프로그램이 예측 불가능하게 일시적으로 중지될 수 있다.
Reference
'Java' 카테고리의 다른 글
| [Java] Garbage Collection(3) - Generational GC (0) | 2022.04.13 |
|---|---|
| [Java] Garbage Collection(2) - 포인터 추적 방식 (0) | 2022.04.12 |
| [Java] Java 8의 특징(7) - 기타 변화들(어노테이션, 병렬 정렬, Metaspace) (0) | 2022.02.28 |
| [Java] Java 8의 특징(6) - CompletableFuture (0) | 2022.02.28 |
| [Java] Java 8의 특징(5) - Date와 Time (0) | 2022.02.26 |