Java Garbage Collector 알고리즘에 대해 알아보자

hj·2021년 9월 27일
0
post-thumbnail

GC 알고리즘

대부분의 GC 알고리즘은 STW(Stop the world)현상을 줄이는 목적으로 만들어 졌다.
다양한 알고리즘이 있지만
Java에서 버전별 채택한 기본 GC 알고리즘인 Parallel GC, G1 GC 대해 알아보자 
 

Parallel GC

Serial GC와 기본적인 알고리즘이 같으나 GC를 처리하는 스레드가 여러개이다.

Young 영역에서 발생한 GC를 Minor GC라고 부르며
Old 영역에서 발생한 GC를 Major GC(혹은 Full GC)라 부른다.

  1. Young Generation
    1-1. 객체를 생성하면 Eden영역에 존재하며 GC가 발생하면
          살아남은 객체들은 Survivor 영역으로 이동하며 계속 쌓인다.
    1-2. 하나의 Survivor 영역이 가득차게 되면 살아남은 객체들은
          다른 Survivor 영역으로 이동하게 되며 가득찬 Survivor 영역은
          아무 데이터도 없는 상태로 존재한다.
    1-3. 이 과정을 반복하다가 살아남은 객체들은 Old 영역으로 이동한다.

    • Survivor 영역 중 하나는 반드시 비어 있는 상태여야 하며
      만약 두 Survivor 영역에 모두 데이터가 존재하거나, 두 영역 모두 사용량이 0이라면 정상적으로 동작하지 않고 있다고 판단해야한다.
  2. Old Generation
    아래 그림처럼 Mark-Sweep-Compact 알고리즘을사용한다.

    2-1. Mark : Old 영역에서 살아있는 객체를 식별한다.
    2-2. Sweep : 앞 부분부터 확인하며 살아있는 객체만 남긴다.
    2-3. Compact : 객체들이 연속되게 쌓이게 가장 앞부분부터 채워넣는다.

G1 GC

전체 힙메모리 영역을 Region이라는 특정한 크기로 나눠서 각 Region의 상태에 따라 그 역할이 동적으로 부여된다.
Region은 대략적으로 2048개로 나뉘며 크기는 1~32MB사이로 지정할 수 있다. (관련 옵션 : XX:G1HeapRegionSize=value)

Eden~Old Region은 위(Parallel GC)에서 설명한 것과 같은 역할
Humongous Region : Region 크기의 50%를 초과하는 객체를 저장하기 위한 영역
available/unused : 아직 사용되지 않은 영역

G1 GC의 기본 원리는 자바 heap의 메모리를 회수할때 최대한 살아 있는 객체가 적게 들어 있는 Region을 수집하는 것이다 (스레드 목표 정지시간(관련옵션 : XX:MaxGCPauseMillis=value)에 최대한 부합하게 하며). 살아 있는 객체가 적을 수록 쓰레기란 의미고 따라서 이름도 쓰레기 우선 수집(Garbage First)이란 이름이 붙게되었다.

  • GC Cycle

    ° parallel 또는 concurrently 처리를 한다.
    ° Space Reclamation는 공간이 너무 파편화되어있거나 Old영역이 임계값에 도달하면 시작된다.
    ° Full GC는 Old 영역 heap 점유율이 너무 높거나 크기가 큰 객체를 많이 할당 했을 때 발생한다.
  1. Young-only
    1-1. young-only collection : eden region의 용량이 한계에
           다 다르면 살아남은 객체들은 survivor region으로 이동이
           되며 이때 young collection은 STW가 발생한다.
    1-2. survivor region에서도 마찬가지로 용량이 한계에 다 다르면
           살아남은 객체들 Old Region으로 이동하고 마찬가지로
           young collection은 STW가 발생한다.
    1-3. 이 행위를 반복하다 임계값(IHOP)에 도달하면
           initial mark 단계가 시작된다.

           임계값의 기본값은 전체 힙의 45%이며
           (XX:InitiatingHeapOccupancyPercent 옵션을 통해 조정이 가능하다)

    G1 GC는 SATB(shapshot-at-the-beginning) 알고리즘을 사용하며
    marking 사이클이 시작될 때 힙메모리에 있는 살아있는 객체 set을 논리적인 스냅샷으로 저장한다.

    1-4. initial mark : root를 mark하며 마킹이 완전히 끝나기
           전까지 Young Collection이 계속 방해 할 수 있다.
    1-5. Root Region Sanning : initial mark에서 마킹된
          객체들의 survivor 영역을 스캔하여 old 영역에 대한
          레퍼런스를 구하고 mark한다.
    1-6. Concurrent marking : 모든 자바 힙에서 접근 가능한
          살아있는 객체를 찾는다.
          이때 Young Collection을 방해를 받을 수 있다.
    1-7. Remark : STW가 발생하며 marking을 마무리하고 SATB버퍼를 비우고,       레퍼런스 처리 및 클래스 언로딩을 수행한다.
    1-8. Cleanup : STW가 발생하며 비어있는 Region을 회수하고
           공간회수 단계가 필요한지 결정한다.
          만약 공간회수 단계가 발생하면 Young-Only단계는
          1회의 Mixed-Collection만 진행한다.

  2. Space Reclamation (공간회수)
    Yonung Collection 외 Old Region도 Compaction하고 비우는게 가능한 여러개의 Mixed-Collection으로 구성됨
    Old Region을 효율적으로 줄일 수 없다 판단되면 종료

참고

Java 8부턴 Permanent 영역이 Metaspace 영역으로 교체되며
Native 메모리 영역(OS가 자동으로 크기를 조절)으로 이동했다.
(참고로 Metaspace영역은 OS에서 자동으로 조절한다지만 JVM 옵션을 통해 Size 설정해주는게 좋다)

* 참고자료

profile
Something Interesting

0개의 댓글