[자바] JAVA GC (Garbage Collection) 개념 및 동작 원리/방식
안녕하세요, 자바 GC (Garbage Collection)에 대해 간단하게 요약하여 정리를 해보고, 동작 원리 및 방식에 대해서도 간략하게 정리를 해보도록 하겠습니다.
GC (Garbage Collection)란
자바의 가비지 컬렉션(Garbage Collection)이란, JVM의 메모리 영역에서 더 이상 참조하지 않는 데이터가 할당된 메모리를 JVM이 자동으로 정리를 해주는 것으로 주로 동적 메모리 영역인 Heap 영역을 대상으로 동작합니다. 개발자가 직접 메모리 관리를 해야 하는 C계열의 언어와 달리, 자바는 JVM이 알아서 불필요한 메모리를 정리하면서 스스로 메모리 관리를 하게 됩니다.
JVM Heap 메모리 구성
GC (Garbage Collection)는 JVM의 메모리영역 중 동적 영역인 Heap 영역을 대상으로 동작을 하는데, 이 Heap 영역은 효율적인 GC를 위해 아래 2가지 가설(Weak generational hypothesis)로 설계가 되었습니다.
- 대부분의 객체는 금방 점근 불가능 상태(unreachable)가 된다.
- 오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다.
위 2가지 가설(Weak generational hypothesis)에 따라 위의 그림과 같이 Heap 메모리 영역이 설계가 되었는데, Heap 영역은 크게 Young Generation 영역과 Old Generation 영역으로 물리적 공간이 나뉘어서 구성이 되었습니다.
- Young Generation 영역 : 새롭게 생성한 객체가 여기에 위치 함, 위의 가설로 대부분의 객체는 unreachable 상태가 되기 때문에 Young 영역에서 사라짐, 이를 Minor CG라 함.
- Old Generation 영역 : Young에서 생존한 객체가 복사 됨, Young영역보다 크게 할당되고 적은 GC 발생, Major GC 혹은 Full GC라고 함.
GC 동작원리
GC가 어떻게 동작하는지 알아보기 전에 Stop the World라는 용어를 알아야 합니다.
- Stop the World : CG가 수행되는 동안 어플리케이션이 멈추는 것, Stop the World 이벤트가 발생하면 GC를 실행하는 스레드를 제외하고 나머지 모든 애플리케이션을 수행하는 스레드들이 GC가 완료될 때까지 동작을 멈추게 됨, Minor GC와 Major GC 모두 Stop the World가 발생하며, 주로 Major GC의 Stop the World가 더 오래 걸림.
다음으로 GC에서 어떤 객체가 Unreachable인지, 즉 정리를 해야 하는 객체인지 판별하기 위해 Mark and Sweep 알고리즘을 사용합니다.
- Mark and Sweep : Root Set (Stack, Method 영역)부터 시작하여 Heap 영역의 객체들이 Reachable 한지를 하나하나 따라가서 (Mark), 참조하지 않는 객체를 판별 후 정리함 (Sweep).
Minor GC
Minor GC가 실행되는 Young 영역은 Eden영역과 2개의 Survivor 영역으로 구성이 되어 있는데, Minor GC의 수행 절차는 아래와 같습니다.
- Eden영역에 신규 객체 할당됨
- Eden영역이 꽉 차면 GC가 수행되고 살아남은 객체가 하나의 Survivor 영역으로 이동, Eden영역에서 계속 동일하게 GC가 수행되고, 객체가 존재하는 Survivor 영역으로만 이동
- 한 개의 Survivor 영역이 가득 차게 되면, 살아남은 객체를 다른 Survivor 영역으로 이동하고 기존 Survivor 영역은 비워짐 (두 Survivor 영역 중 1개는 항상 사용량이 0을 유지)
- 객체가 생존할 때마다 Age가 1씩 늘게 되고, 특정 Age가 되었을 때 Old 영역으로 이동
Major GC
Young 영역에서 넘어온 (Promotion)된 객체들이 Old 영역에 가득 차게 되면 Major GC를 실행하게 되고, Old 영역은 주로 Young 영역보다 크기가 크기 때문에 GC 수행 시간이 더 오래 걸리게 됩니다.
GC 방식
Serial GC (-XX:+UseSerialGC) :
- CPU 코어가 하나일 때 사용하기 위한 방식으로 성능이 좋지 않음
- 위의 Mark and Sweep 알고리즘 후 살아남은 객체를 힙의 앞부분부터 차례대로 정리하여 조각난 메모리를 정리하는 Compation의 과정이 추가되어 동작
Parallel GC (-XX:+UseParallelGC) :
- Serial GC와 동일한 알고리즘으로 동작
- 멀티 스레드로 처리가 되기 때문에 Serial GC보다 속도가 빠름
Parallel Old GC(-XX:+UseParallelOldGC) :
- 위의 Parallel GC와 Old 영역의 알고리즘을 개선
- Mark and Sweep의 개선된 버전인 Mark and Summary 알고리즘 사용
CMS GC (-XX:+UseConcMarkSweepGC) :
- Stop the World 시간을 획기적으로 줄이기 위한 방식으로 모든 요청의 응답 속도가 중요한 애플리케이션에 사용
- 메모리, CPU 등 자원 사용률이 높고, Compaction 단계가 없어 조각난 메모리 다수 발생
- 다음 4단계로 동작: Initial Mark(Stop the World 발생, Root에서 가장 가까운 객체만 찾음) > Concurrent Mark(Stop the World 없이 그다음 참조 객체 추적) -> Remark(Stop the World 발생, 앞의 단계 검증) -> Concurrent Sweep(쓰레기를 정리)
G1 GC (-XX:+UseG1GC) :
- 발전된 H/W 환경의 높은 메모리에서 짧은 Stop the World을 위한 고성능 방식으로 JAVA11의 Default GC
- 메모리 영역을 바둑판 형식으로 Region을 나누고 처리 대상이 많은 Region에 우선적으로 GC 수행
- 기존의 Eden, Survivor, Old 영역 외에 1개 Region의 50% 이상 용량의 객체를 저장하는 Humongous영역과 아직 사용되지 않은 Available/Unused영역으로 구성됨
참조 : https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
https://d2.naver.com/helloworld/1329