
Garbage Collection은 동적으로 할당된 메모리 중 필요 없게 된 객체(Garbage)를 자동으로 정리하는 메모리 관리 기법입니다. 이를 통해, 메모리 누수를 방지하고 효율적인 메모리 관리를 지원합니다.
개발자가 직접 메모리를 관리하는 C/C++에서는 메모리 누수나 잘못된 메모리 접근 같은 문제가 자주 발생했습니다. GC에게 메모리 관리를 위임함으로써 관리의 부담을 줄이고, 개발자가 애플리케이션 로직에 집중할 수 개발 환경을 제공합니다.
하지만, GC에도 단점이 존재합니다. 메모리 관리를 위임했기 때문에 정확하게 메모리가 언제 정리되는지 알 수 없어 제어하기 힘들며, GC의 Stop-the-World 때문에 오버헤드가 발생할 수 있습니다. 이는 애플리케이션 성능 저하로 이어질 수 있기 때문에 최적화 작업인 GC 튜닝이 필요한 상황이 발생할 수 있습니다.
Stop-the-World란?
GC가 작동하는 동안 GC 관련 Thread를 제외한 모든 Thread는 멈추게 되어 프로그램 실행을 멈추는 현상을 의미합니다.
GC는 많은 프로그래밍 언어(파이썬, JS, Go 등)에서 제공하는 메모리 관리 기능입니다. 여기서는 Java 언어를 기반으로 GC가 어떻게 동작하는지 살펴보겠습니다.
JVM의 Runtime Data Area에는 여러 Area가 존재하지만, 동적으로 할당된 객체를 보관하는 곳은 Heap Area입니다. 즉, Heap Area는 GC의 대상이 되는 공간입니다. Heap Area는 다음 그림과 같은 구조를 가지고 있습니다.

각 영역에 대한 특징을 정리하면 다음과 같습니다.
GC는 객체의 도달 가능성(Reachability)이라는 개념을 통해 할당된 메모리를 해제할지 결정합니다. 이를 위해 Root Object에서부터 참조 관계를 따라가며 도달 가능한 객체(Reachable)를 식별합니다. 도달 가능한 객체는 GC의 대상에서 제외되며, 도달 불가능한 객체(Unreachable)는 GC에 의해 정리됩니다.
Root Object란?
객체의 도달 가능성을 판단하기 위한 시작점 역할을 하는 객체로 예시는 다음과 같습니다.
- 스택에 저장된 지역 변수
- 정적 필드
- 활성 상태의 스레드 객체
- JNI로 참조된 객체
GC는 'Mark And Sweep' 알고리즘을 통해 메모리 정리를 수행합니다.
다음 그림과 같이 Root Object에서 시작해 도달 가능한 모든 객체를 식별하고 표시합니다.

다음 그림과 같이 모든 도달 불가능한 객체를 메모리에서 해제합니다.

다음 그림과 같이 필요에 따라 메모리 압축을 수행하여 단편화 문제를 방지합니다.

GC의 대상을 판단하기 위해 사용하는 시작 지점의 역할을 수행하는 객체