JAVA

[JAVA] GC 동작 알고리즘

날아 2023. 2. 5. 17:38

1. GC 대표적인 알고리즘 2가지

  • Reference Counting
    • Root Space : 스택 변수, 전역 변수 등 heap 영역 참조를 담은 변수
    • Reference Count : 몇 가지 방법으로 해당 객체에 접근할 수 있는지를 뜻한다.
    • 카운트가 0이 되면(객체에 접근할 수 있는 방법이 0이 되면) GC에  의해 삭제된다. 
    • 순환참조 문제 등의 한계점이 있다. 

  • Mark and Sweep
    • 루트에서부터 해당 객체에 접근 가능한지를 해제의 기준으로 삼는다.
    • 루트부터 그래프 순회를 통해 연결된 객체들을 찾아내고(Mark) 연결이 끊어진 객체는 삭제한다.(Sweep)
    • 루트로부터 연결된 객체는 Reachable이라 한다. (반대는 Unreachable)
    • Sweep 이후 분산되어 있던 메모리를 한 곳으로 정리하는 것을 메모리 파편화를 막는 Compaction이라고 한다. (필수 과정X)
     

 

Mark and Sweep 특징
  • 의도적으로 GC를 실행시켜야 한다.
  • 애플리케이션 실행과 GC 실행이 병행된다.

2. JVM의 GC - 의도적으로 실행시키기

JVM의 Root Space가 존재하는 곳은 Statck의 로컬 변수, Method Area의 Static 변수, Native Method Stack의 JNI 참조이다.

 

JVM GC는 의도적으로 GC를 실행시켜야 한다고 했다. 그렇다면 기준이 무엇일까?

이를 알기위해서는 JVM의 heap 영역을 살펴보아야한다. 

heap 영역은 Young Generation 과 Old Generation으로 나뉜다. 

  • minor GC : Young Generaion에서 발생
  • major GC : Old Generation에서 발생

 

Young Generation
  • Eden : 새롭게 생성된 객체들이 할당되는 영역 
  • Survival 영역 : minor GC에서부터 살아남은 객체들이 존재하는 영역 
    • Survival 영역은 0이나 1중 둘 중 하나는 반드시 비어있어야 한다. 
Minor GC 실행과정
  1. 새로운 영역들이 Eden 영역에 할당된다. 만약 Eden 영역이 꽉 찼을 경우 minor GC가 일어난다. Mark and Sweep 방식으로 루트로부터 Reachable이라 판단된 객체는 Survival 0 영역으로 옮겨진다. 
  2. Survival 0으로 옮겨진 객체들은 age-bit이 0에서 1로 증가한다. (minor Sti에서 살아남을 때마다 age-bit는 증가한다.)
  3. 시간이 흘러 다시 Eden 영역이 꽉 차면 minor GC가 일어나고, Survival 1 영역으로 옮겨진다. 
  4. 이렇게 계속해서 minor GC가 일어나게 되고, Java 8에서는 Parallel GC 방식 사용 기준 age-bit가 15가 되면 오래도록 사용될 객체로 판단하여 객체를 Old generation 에 넘겨준다. 이를 Promotion이라 한다. 
Major GC 실행 과정 
  1. 시간이 흘러 Old generation도 꽉 찼을 때 Major GC가 일어난다. (Mark and Sweep 방식) 
  2. minor GC보다 실행시간이 오래걸린다. 

 

Heap 영역을 두 Generation으로 나눈 이유
  • 대부분의 객체는 금방 접근 불가능한 상태(Unreachable)가 된다.
  • 오래된 객체에서 새로운 객체로의 참조는 아주 적게 존재한다. 
  • 즉, 객체는 대부분 일회성이며 메모리에 오래동안 남아있는 경우는 드물다. 
  • GC도 결국 비용이니, 메모리의 트겅 부분만을 탐색하며 해제하는 것이 효율적이라고 판단했기 때문

3. JVM의 GC - 애플리케이션과 GC 실행 병행

Stop the World
  • GC를 실행하기 위해 JVM이 어플리케이션 실행을 멈추는 것 
    • GC가 실행될 때는 GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업이 중단된다. 
  • Stop the world 시간을 최소화해야 한다. 

 

Serial GC
  • 하나의 쓰레드로 GC를 실행
  • Stop the World 시간이 길다.
  • 싱글 쓰레드 환경 및 Heap이 매우 작을 때 사용한다. 

 

Parallel GC
  • 여러개의 쓰레드로 GC를 진행
  • 멀티코어 환경에서 사용
  • JAVA 8의 default GC 방식 

 

Parallel GC
  • Stop the World 최소화를 위해 고안
  • GC 수집작업을 애플리케이션과 동시에 실행
  • 단점
    • 메모리와 CPU를 많이 사용한다.
    • Mark and Sweep 과정 이후 메모리 파편화를 해결하는 Compaction이 제공되지 않는다.
  • 이후 G1 GC으로 대체되었다. 

 

G1 GC
  • Garbage First
  • Heap을 Region으로 나누어 사용 (Young Generation, Old Generation)
  • JAVA 9부터 default GC 방식

 

 

 

참고

https://www.youtube.com/watch?v=FMUpVA0Vvjw