Java Garbage Collection

양동혁·2021년 7월 25일
1

이건 알아야지!

목록 보기
2/2
post-thumbnail

GC

동적으로 할당된 메모리 영역 중 더이상 사용하지 않는 메모리를 해제하는 것.

수행 작업

  • heap내의 객체 중에서 garbage를 찾아낸다.
  • 찾아낸 garbage를 처리해서 heap의 메모리를 회수한다.

약한 세대 가설 (weak generational hypothesis)

  • 대부분의 객체는 금방 접근 불가능 상태(unreachable)가 된다. -> 금방 가비지가 된다.
  • 오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다.

GC는 이러한 가설의 전제하에 도입되었기 때문에 생명 주기가 짧은 객체에 대한 빠른 생성과 제거를 보장하는 성격을 가지고 있다.

중요 개념

Object Reference

  • reachable 객체
    Root Set 으로 부터 어떤 식으로든 관계가 있는 객체

  • unreachable 객체
    관계가 없는 객체

Root Set: 객체들 간에 참조 사슬의 시작점. 더 알아보기

STW (Stop-The-World)

  • JVM이 GC를 수행하기 위해 애플리케이션의 실행을 멈추는 작업
  • GC를 실행하는 스레드를 제외한 모든 스레드들의 작업이 중단된다.

Mark and Sweep

  • Mark
    Root Set 으로 부터 모든 변수를 스캔하면서 각각 어떤 객체를 참조하고 있는지 찾아서 마킹한다.
    -> reachable, unreachable 객체 식별

  • Sweep
    unreachalbe 객체들을 Heap에서 제거한다.

Compaction

  • sweep 단계에서 발생하는 단편화문제를 해결하기위해 분산된 객체들을 Heap의 시작주소로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 분리한다.

  • GC알고리즘에 따라 사용할 수도 안할수도 있다.

Mark, Sweep, Compaction

JVM Heap메모리 구조

JVM Heap메모리 구조

  • Young Generation
    새로운 객체들이 할당되는 영역으로 생명주기가 짧은 객체가 위치한다. 이 영역에서 발생하는 GC를 Minor GC라고 한다.

  • Old Generation
    Young Generation에서 오랫동안 살아남은 객체들이 이동하여 존재하는 영역으로 생명주기가 긴 객체가 위치한다. 이 영역이 가득차면 발생하는 GC를 Major GC라고 한다.

  • Metaspace
    JDK8 이전의 Perm영역을 대체하는 것으로 클래스나 메소드의 메타정보가 존재하는 영역 (native영역은 Heap에 있지 않으며 OS에 의해 크기가 동적으로 조정된다.)

Survivor 영역(S0, S1) 은 단지 구분하기 위해 0, 1 로 나뉘어져 있으며 우선순위는 없다. 다만, 하나의 영역에 데이터가 존재하면 반드시 다른 영역에는 데이터가 없어야 한다.

GC 동작 과정

GC 동작

  1. 새로운 객체가 Eden영역에 할당된다.

  2. Eden영역이 꽉 차면(더이상 새로운 객체를 할당할 수 없을 때) Minor GC가 발생한다. -> Mark and Sweep 수행

  3. reachable객체는 하나의 Survivor영역으로 이동하고 unreachable객체의 메모리는 해제된다.

  4. 객체의 생존 횟수를 카운트하기 위해 Minor GC 에서 객체가 살아남은 횟수를 의미하는 age를 object header에 기록한다. 이때 age값이 1증가한다.

  5. Eden영역이 다시 가득차게 되면 Eden과 사용중인 Survivor영역에서 Minor GC가 발생하고 reachable객체는 사용하지 않는 Survivor영역으로 이동한다. 이때도 역시 살아남은 객체는 age값이 1증가한다.

Minor GC가 수행될 때 마다 살아남은 객체는 age값 1증가한다.

  1. 객체의 age가 임계점(MaxTenuringThreshold)에 도달하면 Old Generation으로 이동. (이때 이동되는 객체들을 promoted되었다고 한다.)

  2. promted된 객체들로 Old Generation이 가득차면 Major GC발생한다. Old Generation 영역은 보통 Young Generation영역보다 크게 할당된다.

약한 세대 가설에 따라 대부분의 객체는 금방 unreachable상태가 되기 때문에 Minor GC는 자주 발생하고, Minor GC가 수행되었을 때 수거되는 메모리가 많다. 반면, Major GC는 Minor GC보다 더 오래걸리며(STW가 길기 때문) 수거되는 메모리가 적다.

GC 종류

Serial GC

  • GC를 처리하는 스레드가 1개(싱글 스레드)이기 때문에 다른 GC에 비해 STW가 길다.
  • Mark-Sweep-Compact 알고리즘 사용

메모리나 cpu core가 부족할 때 사용할 수 있으며, 멀티 프로세스 환경에서도 소형 데이터셋(최대 100MB 정도)를 다루는 애플리케이션이면 쓸만하다.

Parallel GC

  • Java8의 default GC
  • Young Generation 영역의 GC(Minor GC)를 멀티 스레드로 수행하며(병렬로 수행), Major GC는 싱글 스레드로 동작한다.
  • Serial GC에 비해 STW시간 감소
  • Mark-Sweep-Compact 알고리즘 사용

serial gc, parallel gc비교

Parallel Old GC

  • Parallel GC와 Old Generation영역의 GC알고리즘만 다름, Old Generation영역에서도 멀티 스레드로 동작
  • Mark-Summary-Compaction 알고리즘 사용.
  • Summary 단계에서는 이미 GC가 수행된 영역에서 살아있는 객체를 식별하는 작업을 진행한다는 점이 Sweep과 다르며 이는 Old GC 처리량을 늘려주기위한 작업이다.(앞서 GC를 수행한 영역에 대해서 별도로 살아 있는 객체를 식별)

CMS GC(Concurrent-Mask-Sweep)

  • STW를 줄이기 귀해 고안됨.
  • Compaction이 없기 때문에 메모리 단편화 발생
  • GC대상을 파악하는 과정이 복잡한 여러 단계로 수행되므로 다른 GC대비 cpu사용량 높다.

serial, cms비교

  1. Inital Mark
    Root Set에서 참조상 가까운 객체만 1차적으로 찾아가며 unreachable객체를 판단하고 종료. 탐색깊이가 얕으므로 STW가 짧다.

  2. Concurrent Mask
    Inital Mark단계에서 GC대상으로 식별된 객체들을 따라가며 참조가 끊긴 객체 확인. 다른 스레드가 실행 중인 상태에서 동시에 진행(STW 없음)

  3. Remaak
    Concurrent Mark 단계의 결과를 검증. 이전 단계에서 식별한 객체를 다시 추적하여 추가로 확인되거나 참조가 제거되었는지 확정한다. Remark단계는 STW를 유발하기 때문에 STW 시간을 최대한 줄이기 위해 멀티스레드로 수행된다.

  4. Concurrent Sweep
    unreachable객체 정리, 다른 스레드가 실행되고 있는 상황에서 진행(STW 없음)

CNS GC

G1 GC(Garbage First)

G1 GC는 보완이 필요합니다! 참고만해주세요.

  • CMS GC 개선형, java 9+의 default gc
  • 쓰레기로 가득찬 Heap 영역을 집중적으로 수집.
  • 큰 메모리를 가진 멀티 프로세서 시스템에서 사용
  • GC 일시 정지 시간을 최소화하면서, 따로 설정을 하지 않아도 가능한 한 처리량(throughput)도 확보하는 것이 G1GC의 목표.
  • Heap을 일정한 크기의 Region으로 나누고, 전체 Heap이 아닌 Region단위로 탐색.

Region

  • G1 GC에서는 Region이라는 개념을 새로 도입했다. 자바 Heap공간을 고정된 크기의 Region들로 나누며, 이 Region들을 free한 Region들의 리스트 형태로 관리한다.
  • 메모리 공간이 필요 해지면, Free Region은 Young영역이나 Old영역으로 할당되며, Region이 비어지면 이 Region은 다시 Free Region 리스트로 돌아간다.
  • Region의 크기는 1MB ~ 32MB로 전체 Heap 사이즈 용량이 2048개의 Region으로 나누어질 수 있도록하는 범위 내에서 결정된다.
  • Region이 비어지면 이 Region은 다시 Free Region 리스트로 돌아간다.

기본 원리

자바 Heap의 메모리를 회수할 때 최대한 살아있는 객체가 적게 들어있는 Region을 수집한다. 가장 살아있는 객체가 적을수록 garbage란 의미이고, 따라서 이름도 쓰레기 우선(Garbage First) 수집 이란 이름이 붙게 되었다.

구조

G1 GC에는 추가되는 영역이 있다.

  • Humongous : Region 크기의 50%를 초과하는 큰 객체를 저장하기 위한 공간이며, 이 Region 에서는 GC 동작이 최적으로 동작하지 않는다.

  • Available/Unused : 아직 사용되지 않은 Region을 의미한다.

G1 GC

G1 GC에서 중요한 점은, 전통적인 GC의 힙 구조와는 달리 Young 이나 Old 영역이 인접해 있지 않다는 점이다. 이는 영역의 사이즈가 필요에 따라서 동적으로 바뀔 수 있다는 점에서 편리하다.

Adaptive 사이즈가 지원되는 Parallel Old GC와 같은 GC 알고리즘은 각 영역들이 확장될 일을 대비해 여분의 공간을 남겨둔다. 그렇게 함으로서 Young 영역과 Old 영역을 인접한 상태로 둘 수 있다. CMS의 경우엔 자바의 heap 사이즈와 영역의 사이즈를 조정하기 위해서는 Full GC가 필요하다.

반면 G1 GC는 영역의 개념이 물리적으로 존재하지 않고 논리적으로만 존재함으로써 공간과 시간을 아낄 수 있다. (young 영역의 region들과 그 외에는 old 영역의 region들이 있지 이를 물리적 위치로 구분하지 않는다.)

전통적인 GC Layout
전통적인 GC Layout

동작 과정

Minor GC를 수행할 때 STW가 발생하며, STW 시간을 최대한 줄이기 위해 멀티스레드로 GC를 수행한다. Young GC는 각 Region 중 GC대상 객체가 가장 많은 Region(Eden 또는 Survivor 역할) 에서 수행 되며, 이 Region 에서 살아남은 객체를 다른 Region(Survivor 역할)으로 옮긴 후, 비워진 Region을 사용가능한 Region으로 돌리는 형태 로 동작한다.

G1 GC 동작과정

  • Initial Mark (STW 발생)
    Old Region에 존재하는 객체들이 참조하는 Survivor Region을 찾는다.

  • Root Region Scan
    Initial Mark에서 찾은 Survivor Region에 대한 GC 대상 객체 스캔 작업을 진행한다.

  • Concurrent Mark
    전체 Heap의 Region에 대해 스캔 작업을 진행하며, GC 대상 객체가 발견되지 않은 Region은 이후 단계를 처리하는데 제외되도록 한다.

  • Remark (STW 발생)
    최종적으로 GC 대상에서 제외될 객체(살아남을 객체)를 식별해낸다.

  • Cleanup (STW 발생)
    살아있는 객체가 가장 적은 Region 에 대한 미사용 객체 제거 수행한다. 이후 STW를 끝내고, 앞선 GC 과정에서 완전히 비워진 Region 을 Freelist에 추가하여 재사용될 수 있게 한다.

  • Copy (STW 발생)
    GC 대상 Region이었지만 Cleanup 과정에서 완전히 비워지지 않은 Region의 살아남은 객체들을 새로운(Available/Unused) Region에 복사하여 Compaction 작업을 수행한다.

참고

https://johngrib.github.io/wiki/jvm-memory/
https://d2.naver.com/helloworld/1329
https://plumbr.io/handbook/garbage-collection-in-java/minor-gc-major-gc-full-gc
https://www.holaxprogramming.com/2013/07/20/java-jvm-gc/
https://mirinae312.github.io/develop/2018/06/04/jvm_gc.html
https://medium.com/@joongwon/jvm-garbage-collection-algorithms-3869b7b0aa6f
https://luavis.me/server/g1-gc (G1 GC)

profile
BackEnd Developer, Business Driven Development

0개의 댓글