본문 바로가기

Java

Garbage Collector (정의와 종류)

Garbage Collector ( 정의, 종류 )

GC란?

자바 언어로 프로그래밍을 할 때 우리는 인스턴스를 생성하고 사용한 이후에 이에 대한 메모리를 해제하지 않는다. 메모리를 직접적으로 관리해줘야 하는 언어와 달리 JVM 기반 언어는 Garbage Collector가 사용되지 않는 메모리 영역(Garbage)을 청소해주기 때문이다.
이렇게 Garbage Collector의 대상이 되는 영역은 JVM 메모리의 Heap 영역이다.

  • Weak Generational Hypothesis (JVM의 GC는 두 가지 가설을 전제로 역할을 수행한다.)
    1. 대부분의 객체는 금방 접근할 수 없는(Unreachable) 상태가 된다.
    2. 오래된 객체에서 새로운 객체로의 참조는 매우 드물게 발생한다.

  • 위의 그림을 보면 실제로 대부분의 객체의 수명이 매우 짧음을 알 수 있다.

 

Mark and Sweep

GC는 기본적으로 두 개의 간단한 스텝으로 메모리를 관리한다.

  1. Mark : GC는 해당 메모리 조각이 사용되는지 사용되지 않는지를 체크한다.
    • 이렇게 사용되는지를 판단하려면 Root Set(Heap에 저장된 객체의 레퍼런스를 담고있는 영역(Stack, Java Native Stack 등))으로부터 Reachable 한지를 판단한다.
  2. Sweep : 사용되지 않는다고 식별된 객체를 해제한다.
    (+ Compact 단계가 포함되기도 한다. 사용되는 메모리 조각을 차례로 정리하는 작업)

 

JVM Heap 메모리 영역


GC가 관리하는 JVM Heap 메모리 영역은 크게 Young, Old Generation으로 나누고 Young Generation은 다시 Eden, Survivor1 Survivor2로 나뉜다.

  • Minor GC 는 Young 영역에서 일어나는 GC를, Major GC 는 Old 영역에서 일어나는 GC를 말한다. Major GC는 Stop-the-world를 발생시킨다.

Minor GC

  1. 객체가 생성되면 해당 객체는 Eden 영역에 메모리를 할당한다. 그리고 이 Eden 영역이 가득 차게되면 Minor GC가 발생하게된다.
  2. Minor GC는 Eden + Survivor1 영역에서 살아남은 객체를 Survivor2로 이동시킨다.
  3. 다시 Eden 영역이 가득차면 Eden + Survivor2 영역에서 Reachable한지 판단하고 살아남은 객체를 Survivor1로 이동시킨다.
    • 항상 Survivor1, Survivor2 중 하나는 비어있어야 한다.
  4. 이렇게 Minor GC를 반복 수행하면서 살아남은 객체들의 age 값을 증가시킨다.
  5. age 값이 일정 수준을 넘으면 해당 객체는 Old 영역으로 이동시킨다. (이 행위를 Promotion이라고 한다.)

 

Major GC

  1. age 값이 일정 수준 이상인 객체들이 쌓이다 보면 Old 영역도 가득 차게된다.
  2. 이 때 Old영역을 대상으로 GC가 발생하는데 이를 Major GC라고 한다.
  3. Major GC는 stop-the-world (애플리케이션이 중지되고 오직 GC를 수행하는 쓰레드만 작업을 수행하는 시간)가 발생한다.
  • 주로 Major GC의 시간을 줄이기 위해서 각각의 GC 알고리즘이 만들어졌다고 볼 수 있다.
    • Serial GC
    • Parallel GC
    • Parallel Old GC
    • Cms GC
    • G1GC
    • ZGC다양한 GC 알고리즘
    • Serial GC
  • 지금은 거의 쓰이지 않는 GC 이다. 기본적으로 위의 Mark & Sweep 과정으로 GC를 수행한다.
  • 특징으로는 하나의 쓰레드만을 사용하여 GC를 수행하기 때문에 stop-the-world 시간이 길다는 단점이 있다.Parallel GC
  • Serial GC와 거의 비슷하지만 Major GC 작업을 수행할 때 여러 스레드가 동시에 병렬로 처리하기 때문에 시간을 단축시킬 수 있게 되었다.
  • java 8의 기본 GC 알고리즘이다.CMS(Concurrent Mark and Sweep) GC
  • CMS GC는 애플리케이션의 pause 타임, 즉 garbage collection 시간을 줄이려고 애플리케이션이 실행되는 중에 Concurrent 하게 GC를 수행한다.

The CMS collector pauses an application twice during a concurrent collection cycle. The first pause is to mark as live the objects directly reachable from the roots (for example, object references from application thread stacks and registers, static objects, and so on) and from elsewhere in the heap (for example, the young generation).

This first pause is referred to as the initial mark pause. The second pause comes at the end of the concurrent tracing phase and finds objects that were missed by the concurrent tracing due to updates by the application threads of references in an object after the CMS collector had finished tracing that object. This second pause is referred to as the remark pause.

https://docs.oracle.com/en/java/javase/11/gctuning/concurrent-mark-sweep-cms-collector.html#GUID-937A32AD-E2EA-4109-823D-A66D001A1807

 

  • 원리
    1. Initial Mark 시에 Root Set으로부터 첫 번째로 참조되는 객체만을 Mark 한다. (1단계 참조만을 검색하므로 매우 짧은 시간동안 stop-the-world 발생)
    2. 이후 Marking 단계에서는 애플리케이션의 로직과 동시에 수행되게 된다.
    3. 다시 한 번 Remark 하는 단계에서 stop-the-world가 짧게 발생한다.
    4. 마지막으로 sweeping 단계에서도 애플리케이션 로직과 같이 수행된다.
  • 두 가지 문제
    1. 위와 같이 CMS Collector가 작업을 수행하는데 Old 영역이 채워지는 속도가 더 빠를 수 있다. 이 경우 stop-the-world가 발생할 수 있다.
    2. CMS GC는 애플리케이션이 거의 중단되지 않는다는 장점이 있지만 Compaction을 수행하지 않아 메모리가 듬성듬성 남는 부작용이 생긴다. 이렇게 진행되다가 Compaction이 발생하게 되면 갑자기 stop-the-world 시간이 길어지게 될 수 있다.
  • 이러한 문제들로 인해 java 9 버전 이후 부터 depercaated 되었다.

G1GC

  • Java 9 이후부터 Default GC로 사용되고 있다.
  • 기본 컨셉
    • G1은 이전의 애플리케이션의 동작과 Pause Time을 기록하여 효율적으로 GC를 수행할 수 있도록 한다. Garbage가 많은 area를 판단하여 이를 우선적으로 처리할 수 있다.(Garbage First)
    • Heap 메모리 영역을 같은 크기의 Region으로 나눠서 메모리를 할당한다.

  • Region의 종류
    • Young
      • Eden(Red)
      • Survivor(Red with S)
    • Old
      • Light Blue
      • Houmogous : Region의 1/2 크기 이상인 객체에 대하여 할당한다.
  • G1
    • Young-Only 단계는 크게 두 단계로 나눌 수 있다.
      • Normal Young Collection : 이용가능한 메모리 영역이 점차 Old 영역으로 변하는 단계이다.
        • Eden으로 할당된 영역이 가득차면 이를 다른 survivor region(garbage가 많은)과 함께 minor gc를 수행하며 비워져있는 region으로 이동시킨다. 이 작업이 반복되면 age가 증가하며 Old 영역으로 promotion 한다
      • Concurrent Start Young Collection : Normal Young Collection이 진행되다가 Old 영역의 점유율이 threshold를 넘으면 Concurrent Start Young Collection이 진행된다.
        • Concurrent Start : 현재 접근가능한 모든 객체를 식별(Marking)한다. 다음 두 단계를 진행할 때 까지 Marking을 계속한다.
        • Remark(Stop-the-world 발생) : 이 단계에서 마킹을 종료하고, 전역 참조, 클래스 언로딩, 비어있는 공간 확보, 내부 자료구조 정리 등을 한다.
        • Clean up(Stop-the-world 발생) : Space Reclamation 단계가 필요한지를 판단해서 필요시 수행시킨다.
    • Space Reclamation 단계에서는 Young-Only에서 수행하는 것과 함께 Old영역의 Major GC 작업을 수행한다.

  • 추가적으로 알아볼 내용
    • ZGC
    • GC 모니터링
    • GC 튜닝

Reference