Garbage Collection

Jerry·2025년 7월 23일

가비지 컬렉션(Garbage Collection)이란?

  • 불필요해진 객체(더 이상 참조되지 않는 객체)를 자동으로 탐지하여 메모리에서 해제하는 JVM의 메모리 관리 기법
  • C, C++과 달리 free()delete 같은 명시적 해제가 필요 없음 → 메모리 누수 위험 대폭 감소

GC의 동작 원리

객체 lifecycle

  1. 객체 생성: new 등으로 힙에 메모리 할당
  2. 참조 유지: 하나 이상의 변수/필드에서 참조하면 "reachable"
  3. 참조 소멸: 변수/필드에서 연결이 모두 끊기면 "unreachable" 상태
  4. GC 대상: 더 이상 어떤 변수에서도 접근할 수 없는 객체는 가비지(Garbage)로 간주

GC의 트리거(언제 실행?)

  • JVM이 힙의 사용량이 일정 임계치에 도달하거나, 명시적으로 System.gc() 호출 시
  • JVM이 "언제" 실행할지는 자율적으로 판단 (일반적으로 자동)

JVM 메모리 구조와 GC

※ Young Generation, Old Generation 구분 예시

Generational GC 구조

  • Young Generation:
    • 새로 생성된 객체 저장 (Eden, Survivor S0/S1)
    • 대부분의 객체는 생성 후 곧바로 소멸(“객체의 대부분은 오래 살아남지 않는다”)
  • Old Generation:
    • Young에서 살아남은(여러 GC를 견딘) 장수 객체 저장
  • Metaspace(메타스페이스):
    • 클래스 정보, static 변수 등 (PermGen은 자바8부터 Metaspace로 변경)

주요 GC 알고리즘(방식)

Mark and Sweep (표시-삭제)

  • Mark: Reachable(도달 가능한) 객체를 모두 표시
  • Sweep: 표시되지 않은 객체는 메모리에서 해제

Stop-the-world

  • GC 수행 시 애플리케이션 스레드 모두 일시 정지
  • GC 후에 다시 실행
  • 짧게 끊기는 “멈춤 현상”이 단점

Minor GC vs Major GC

  • Minor GC: Young Generation만 GC (일반적으로 짧고 빈번함)
  • Major GC(Full GC): Old Generation 포함 전체 GC (더 느리고 애플리케이션 일시 정지 시간이 길다)

복사(Copying), 압축(Compaction), 참조 업데이트

  • Young GC는 Copying 방식(Eden → Survivor)으로 빠르게 작동
  • Old GC는 Mark-Sweep-Compact로 메모리 단편화 방지

주요 JVM GC 구현체

GC 종류특징사용처/장단점
Serial GC단일 스레드로 동작, 단순, 소규모 앱/테스트용적은 메모리, 단일 CPU
Parallel GC(Default) 다중 스레드로 Young GC, 빠른 Throughput일반 서버 앱, 성능 좋음
CMS (Concurrent Mark-Sweep)Old 영역을 병행으로 마킹/스윕Stop-the-world 최소화, 더 많은 CPU
G1 GCJava 9 이상 기본, Region 단위 관리, Predictable대용량, 낮은 지연
ZGC, Shenandoah극한의 저지연, 초대용량 시스템최신 Java, 하드웨어 여유 필요

GC 튜닝 실무 팁

  • JVM 옵션으로 GC 종류와 Heap 크기 설정
    • 예: -Xmx2g -Xms2g -XX:+UseG1GC
  • 로그 분석으로 GC pause time, frequency 모니터링
    • 예: -XX:+PrintGCDetails -Xloggc:gc.log
  • 객체 생성 최소화 & 참조 빨리 끊기 (ex. null 할당)
  • 불필요한 Static, 캐시 객체 주의 (GC에서 살아남기 쉬움)

가비지 컬렉션의 한계/주의점

  • Stop-the-world 현상: GC 도중 모든 스레드가 멈춤 → 레이턴시 민감한 서비스(게임, 금융)에서 주의
  • 메모리 누수: 참조가 남아 있으면(GC Root에 연결된 객체) GC가 회수 못함
  • GC 튜닝 난이도: 워크로드에 따라 최적 세팅이 다름(서버, 클라우드 환경 등)

실제 코드 예시

public class GcExample {
    public static void main(String[] args) {
        for (int i = 0; i < 100_000; i++) {
            String data = new String("data-" + i);
        }
        // 대부분의 data 변수는 스코프를 벗어나며, GC의 대상이 됨
        System.gc(); // (GC 트리거 권유, 권장X)
    }
}
  • 위 코드에서 data는 반복문이 끝나면 참조가 끊기므로 GC 대상

요약 표

용어/기능설명
Minor GCYoung 영역 GC (빠르고 짧음)
Major(Full) GCOld 포함 전체 GC (길고 느림)
Stop-the-worldGC 중 JVM의 모든 스레드 일시 정지
Mark-and-Sweep살아있는 객체 표시 후 미사용 객체 제거
Generational GCYoung/Old 세대 구분, 객체 생존 기반
G1, ZGC, CMS 등최신 GC 전략, 저지연/대용량 지원

Reference

profile
Backend engineer

0개의 댓글