가비지 컬렉션(Garbage Collection)이란?
쓰레기 수집은 메모리 관리 기법 중의 하나로, 프로그램이 동적으로 할당했던 메모리 영역 중에서 필요없게 된 영역을 해제하는 기능
C/C++ 언어에서는 프로그래머가 수동으로 메모리 할당과 해제를 일일이 해주어야 했다.
하지만 Java에서는 JVM이 가비지 컬렉션이라는 프로세스를 통해 프로그램 메모리를 관리해주기 때문에 한정된 메모리의 효율적인 사용이 가능하고, 프로그래머가 메모리 누수(Memory Leak) 문제에 대해 관리하지 않아도 된다는 장점이 있다.
가비지 컬렉션(GC)은 자바 뿐만 아니라 파이썬, 자바스크립트, Go 언어 등 많은 언어에 기본적으로 내장되어 있다.
GC의 단점
- 메모리가 언제 해제되는지 정확하게 알 수 없어 제어하기 힘들다.
- 가비지 컬렉션(GC)이 동작하는 동안에는 다른 동작을 멈추기 때문에 오버헤드가 발생한다.
이를 Stop-The-World 라 한다.
Stop-The-World
GC를 수행하기 위해 JVM이 프로그램 실행을 멈추는 것
GC가 작동하는 동안 GC 관련 Thread를 제외한 모든 Thread는 멈추게 된다.
어떤 GC 알고리즘을 사용하더라도 stop-the-world 는 발생하게 되는데, 대개의 경우 GC 튜닝은 이 stop-the-world 시간을 줄이는 것이다.
이로 인해 GC가 너무 자주 실행되면 소프트웨어 성능이 하락하기도 한다.
이런 특성에 의해 실시간으로 계속 동작해주어야 하는 시스템일 경우 잠깐의 소프트웨어 정지가 목표 결과에 큰 영향을 끼칠 수 있기 때문에 GC의 사용이 적합하지 않을 수 있다.
따라서 어플리케이션의 사용성을 유지하면서 효율적이게 GC를 실행하는 최적화 작업(GC 튜닝)이 개발자에게 큰 숙제라고 할 수 있다.
GC의 대상
기본적으로 JVM의 메모리는 총 5가지 영역(class, stack, heap, native method, PC)으로 나뉘는데, GC는 힙 메모리만 다룬다.

GC가 주로 동작하는 대상은 Heap 영역 내의 객체 중에서 참조되지 않은(Unreachable) 데이터이다.
일반적으로 다음과 같은 경우에 GC의 대상이 된다
- 객체가 NULL인 경우
- 블럭 실행 종료 후, 블럭 안에서 생성된 객체
- 부모 객체가 NULL인 경우, 포함하는 자식 객체
GC 메모리 해제 과정
Mark And Sweep
Mark-Sweep 이란 다양한 GC에서 사용되는 객체를 솎아내는 내부 알고리즘이다.
가비지 컬렉션이 동작하는 아주 기본적인 알고리즘이다.

가비지 컬렉션이 될 대상 객체를 식별(Mark)하고 제거(Sweep)하며 객체가 제거되어 파편화된 메모리 영역을 앞에서부터 채워나가는 작업(Compaction)을 수행하게 된다
- Mark 과정 : 먼저 Root Space로부터 그래프 순회를 통해 연결된 객체들을 찾아내어 각각 어떤 객체를 참조하고 있는지 찾아서 마킹한다.
- Sweep 과정 : 참조하고 있지 않은 객체 즉 Unreachable 객체들을 Heap에서 제거한다.
- Compact 과정 : Sweep 후에 분산된 객체들을 Heap의 시작 주소로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 압축한다. (가비지 컬렉터 종류에 따라 하지 않는 경우도 있다)
GC 동작 과정
heap 메모리 구조
JVM의 힙(heap) 영역은 동적으로 레퍼런스 데이터가 저장되는 공간, 가비지 컬렉션의 대상이 되는 공간이다.

Heap영역은 처음 설계될 때 다음의 2가지를 전제 (Weak Generational Hypothesis)로 설계되었다.
- 신규로 생성한 객체의 대부분은 금방 사용하지 않는 상태가 된다.
- 오래된 객체에서 새로운 객체로의 참조는 아주 적게 존재한다.
즉, 객체는 대부분 일회성되며, 메모리에 오랫동안 남아있는 경우는 드물다.
이 가설에 기반하여 자바는 Young 영역과 Old 영역으로 메모리를 분할하고, 신규로 생성되는 객체는 Young 영역에 보관하고, 오랫동안 살아남은 객체는 Old 영역에 보관한다.
동작 과정
- 어떠한 새로운 객체가 들어오면 Eden Space에 할당한다.
- Eden space가 가득 차게 되면, minor garbage collection이 시작된다.
- 참조되는 객체들은 첫 번째 survivor(S0)로 이동되어지고, 비 참조 객체는 Eden space가 clear 될 때 반환된다.
- 다음 minor GC 때, 비 참조 객체는 삭제되고 참조 객체는 두 번째 survivor space로 이동하게 된다.
게다가 최근 minor GC에서 S0로 이동된 객체들도 age가 증가하고 S1 공간으로 이동한다.
한번 모든 surviving 객체들이 S1으로 이동하게 되면 S0와 Eden 공간은 Clear 된다.
주의해야 할 점은 이제는 다른 aged 객체들을 Survivor space에 가지게 되었다는 것이다.
- 다음 minor GC 때, 같은 과정이 반복된다. 참조되는 객체들은 S0로 이동한다.
살아남은 객체들은 aged된다. 그리고 Eden과 S1 공간은 Clear 된다.
- minor GC 후 aged 오브젝트들이 일정한 age threshold(문지방)을 넘게 되면 그들은 young generation에서 old로 promotion 된다.
- minor GC가 계속되고 계속해서 객체들이 Old Generation으로 이동한다.
- 결국 major GC가 old Generation에 시행되고, old Generation은 Clear 되고, 공간이 Compact 된다.
[참고자료]
링크1🔗
링크2🔗
링크3🔗
링크4🔗