[F-Lab 모각코 챌린지] 4일차 GC 복습
F-Lab 에서 진행 한 모각코 챌린지(4일차) 내용을 정리 한 글입니다. Java 의 GC 개념들 중 Root, Marking & Sweeping, G1 GC, 메모리 누수에 대해 간략하게 설명합니다.
GC - Root
가비지 컬렉터가 어떤 객체가 유효한지(아직 참조되고 있는지) 판단하기 위한 시작점
- 시스템 클래스 로더에 의해 로드된 클래스
- 액티브 스레드 (현재 실행중인 모든 스레드)
- 메소드에 의해 참조된 로컬 변수와 매개 변수
- 정적 변수 (어떤 객체를 참조하고 있다가 참조가 제거 되어 더 이상 해당 객체에 접근 할 수 없을 때)
GC - 마크 스윕 알고리즘
Java GC 의 기본 알고리즘
Java 1 에서 최초로 도입 되었으며 점차 발전하여 현재는 많은 파생 알고리즘을 낳았다. 모든 GC 들이 Stop-The-World 문제가 있는데, 버전이 올라가면서 점점 해당 문제를 개선하는 방향으로 개발되고 있다.
Stop-The-World : 모든 스레드를 멈추고 해당 알고리즘 수행
(여기서는 마킹 단계에서 객체 그래프 탐색을 위해 모든 스레드를 일시적으로 멈춤)
두 단계로 이루어짐
- Marking: 마킹
- Sweeping: 스윕
Marking: 마킹
- 도달 가능한 객체를 찾아 마킹
- 마킹 되지 않은 객체들은 가비지로 간주
Sweeping: 스윕
마킹되지 않은 객체들을 메모리에서 해제
내가 자주 사용하는 GC 가 무엇?
Java 11 의 G1(Garbage First) GC
![G1 GC 의 이해를 돕기 위한 이미지. (빨간색: Young / 빨간색S: Survivor / 파란색H: Old)](https://blog.pollra.com/content/images/2023/05/image.png)
전체 힙 공간을 여러 개의 작은 영역(Region)으로 분할, 각 영역을 독립적으로 관리하여 효율성 향상
G1 GC 의 특징
- 분산된 가비지 컬렉션: 전체 힙을 스캔하는 알고리즘의 비용 감소
- Stop-The-World 시간 감소: 분산된 가비지 컬렉션을 통해 STW 시간을 감소
- 병렬 처리: 가비지 컬렉션을 멀티 스레드로 수행.
(단, Region 별 Minor GC, Major GC 수행 후 에도 공간이 부족 한 경우 싱글 스레드 기반의 Full GC 가 동작함)
프로세스
1) Pre Evacuate Collection Set(컬렉션 집합 사전 비우기)
- G1 GC 가 수집 할 Collection Set 을 사전에 준비하는 과정.
- 힙 영역을 작은 영역으로 분할하고 어떤 영역을 수집 할지 결정
2) Merge Heap Roots
- 힙 루트(가비지 컬렉션의 시작점)를 병합
- 마킹 작업을 효율적으로 수행 할 수 있도록 준비
3) Evacuate Collection Set
- 1에서 준비된 Collection Set 에 포함된 객체들을
살아있는 객체 영역(Live Object Set)
으로 복사 - 객체들이 새로운 위치로 이동하며 메모리 단편화를 최소화 하기 위해 객체를 연속된 메모리 영역으로 배치
4) Post Evacuate Collection Set
- G1 GC 가 복사된 객체들이 포함된 영역을 정리 하고 빈 공간을 식별하여 가용 메모리로 전환
메모리 누수가 발생하는 원인들?
- 객체 참조 유지: 객체를 참조하고 있는 참조 변수를 해제하지 않고 계속 유지하는 경우. 특히 긴 생명주기를 가지는 객체를 참조하는 경우 문제가 될 수 있음.
(정적 컬렉션, 캐시, 리스너 등에서 발생 가능성 있음) - 스레드 메모리 누수: 스레드가 종료되지 않고 계속 실행되는 경우, 해당 스레드에서 참조하는 객체들도 메모리에서 해제되지 않음.
(스레드 풀 에서 스레드를 종료하지 않는 경우 메모리 누수 가능성 있음) - 리소스 누수: 파일, 네트워크 연결, 데이터베이스 연결 등과 같은 리소스를 올바르게 해제하지 않는 경우, 해당 리소스가 점유한 메모리는 해제되지 않을 수 있음
- 캐시 관리: 캐시에서 오래된 데이터를 제거하지 않는 경우 메모리 누수 가능성