가비지 컬렉터란?
자바의 메모리 관리 방법 중의 하나로 JVM(자바 가상 머신)의 Heap 영역에서 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객체(Garbage)를 모아 주기적으로 제거하는 프로세스
줄여서 GC라고도 한다.
C, C++ 등의 프로그래밍 언어는 가비지 컬렉터가 존재하지 않아 프로그래머가 free()와 같은 함수를 사용해서 수동으로 메모리 할당과 해제를 일일이 진행했어야 했다.
#include <stdio.h>
#include <stdlib.h>
int main() {
int* ptr = (int*)malloc(sizeof(int)); // 동적 메모리 할당
if (ptr == NULL) return 1;
*ptr = 100;
printf("값: %d\n", *ptr);
free(ptr); // 메모리 해제
return 0;
}
이런식으로 malloc으로 메모리를 할당한 후 free로 수동 해제가 필요했다.
하지만 Java, C# 등의 언어는 처음부터 가비지 컬렉터가 존재하여 프로그래머가 동적으로 할당한 메모리 영역의 전체를 완벽하게 관리할 필요가 없어졌다. 이로 인해 버그를 줄이거나 막을 수 있음!
관리되는 힙에 효율적으로 개체를 할당한다.
더 이상 사용되지 않는 개체를 회수하고 이러한 개체의 메모리를 비워 이후 할당에서 이 메모리를 사용할 수 있도록 한다. 관리되는 개체는 자동으로 시작을 위한 정리된 콘텐츠를 받으므로 개체의 생성자가 모든 데이터 필드를 초기화할 필요가 없다.
개체가 다른 개체에 할당된 메모리를 자체적으로 사용할 수 없도록 하여 메모리 안전성을 제공한다.
하지만 단점도 존재한다.
가비지 컬렉션은 특정 객체가 garbage인지 아닌지 판단하기 위해서 도달성, 도달능력이라는 개념을 적용한다.
어떠한 변수에도 참조(reference)되지 않는 객체는 GC의 대상인데, 이를 도달할 수 없는 객체(Unreachable Object)라고 한다.
public class Test {
public static void main(String[] args) {
String a = new String("hello");
a = null; // "hello"는 이제 누구도 참조하지 않음 → GC 대상
}
}

: 사용 중인 객체를 표시(mark)한 후 사용하지 않는 객체는 제거(sweep)
1) Mark (표시 단계)
2) Sweep(제거 단계)
표시되지 않은 객체(Unreachable)는 메모리에서 제거한다.
: GC가 작동할 때 JVM이 모든 실행을 멈추고 메모리 정리를 시작

하지만, GC가 너무 자주 실행되면 소프트웨어 성능 하락의 문제가 발생한다.
따라서 사용성을 유지하면서 효율적이게 GC를 실행하는 최적화 작업이 필요한데 이러한 최적화 작업을 GC 튜닝이라고 한다.
: JVM은 객체의 생명주기를 기반으로 메모리를 세대별로 나눠서 GC 효율을 높임

1) Young Generation
Minor GC라고도 한다.2) Old (Tenured) Generation
힙 영역은 더욱 효율적인 GC를 위해 Young 영역을 3가지 영역 (Eden, survivor 0, survivor 1)으로 나눈다.
1) Eden
2) survivor 0 / survivor 1
가비지 컬렉터의 동작원리에 대해서 더 자세하게 알게 된 계기가 되었습니다.