JVM - Garbage Collector

Dayon·2024년 4월 16일
2
post-thumbnail

Garbage Collection이 JVM에서 어떻게 작동하는지, 서로 다른 가비지 컬렉터들의 특징과 성능 차이에 대해 알아보자

1. Garbage Collection 이란?

JVM (Java Virtual Machine)

  • JVM is a program that looks like a machine to the programs written to execute in it.
    JVM은 그 안에서 실행되도록 작성된 프로그램에게 기계처럼 보이게 하는 프로그램이다.

  • 운영체제 메모리 영역에 접근하여 메모리를 관리하는 프로그램


메모리 관리의 필요성

모든 프로그램은 실행을 위해 메모리를 할당받아 사용하며, 사용이 끝난 메모리는 시스템에 반환되어야 한다.

  • C, C++ 등 가비지 컬렉션이 없는 언어는 할당했던 메모리를 반환하지 않는다.

    • 시스템의 모든 RAM을 사용하고 프로그램과 컴퓨터가 머물 수도 있다.

    • 메모리가 해제된 후 포인터를 통해 버퍼를 읽고쓰려 시도할때 무작위의 결과가 발생할 수 있다.(Dangling Pointer)

    • 버퍼 오버런, 문자열 조작이 발생 할 수 있다.

      ⇒ 이러한 이유로 로그래머가 수동으로 메모리 할당과 해제를 일일이 해줘야 했었다.

  • 파이썬, 자바스크립트, Go 언어 등많은 프로그래밍 언어에서 가비지 컬렉션이 기본으로 내장


Java의 Garbage Collector

  • JVM Heap 영역에서 사용하지 않는 객체를 삭제하는 프로세스

  • Garbage collection was invented to simplify manual memory mangagement.

    동적으로 할당된 메모리 영역 중 사용하지 않는 영역을 탐지하여 해제하는 기능

    • Heap ⇒ 동적으로 할당한 메모리 영역
      모든 Object 타입의 데이터가 할당, Heap 영역의 Object를 가리키는 참조 변수가 Stack에 할당
    • Stack ⇒ 정적으로 할당한 메모리 영역, Heap영역에서 생성된 Object 의 주소만 참조
  • Java에서는 메모리 할당 해제 프로세스가 가비지 컬렉터에 의해 자동으로 처리된다.


stop-the-world

  • GC를 실행하기 위해 JVM이 애플리케이션 실행을 멈추는 것
  • stop-the-world가 발생하면 GC를 실행하는 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 멈춘다.
  • GC작업을 완료한 이후에 중단했던 작업을 다시 시작
  • 자동으로 처리해준다 해도 메모리가 언제 해제되는지 정확하게 알 수 없어 제어하기 힘들며, 가비지 컬렉션(GC)이 동작하는 동안에는 다른 동작을 멈추기 때문에 오버헤드가 발생되는 문제점
  • 어떠한 Garbage Collector 알고리즘을 사용하더라도 stop-the-world는 발생한다.
    ⇒ GC 튜닝 = stop-the-world의 시간을 줄이는 것
    > "메모리가 5배 더 많다면 성숙한 비복사 공간이 있는 아펠(Appel)식 세대별 컬렉터의 성능은 도달 가능성 기반의 명시적 메모리 관리의 성능과 대등하다. 메모리가 3배 더 많다면 컬렉터의 실행 성능은 명시적 메모리 관리에 비해 평균 17% 느리다. 메모리가 2배인 경우 가비지 컬렉션의 성능은 70% 가까이 하락한다. 물리적 메모리가 부족하면 페이징으로 인해 가비지 컬렉션의 속도는 명시적 메모리 관리에 비해 훨씬 더 느리게 된다.
    > 
    > 
    > [매튜 허츠와 에머리 D. 버거의 2005년 논문](https://people.cs.umass.edu/~emery/pubs/gcvsmalloc.pdf)
    > 
    > !http://linkback.itworld.co.kr/images/onebyone.gif?action_id=e8e4beee07c904b8d7dde7c56153d87
    > 
    > !http://linkback.itworld.co.kr/images/onebyone.gif?action_id=bf7c84ffcaf5b2a97163d6a70229b07
    > 

2. Garbage Collection 동작 방식

Garbage Collection 대상

가비지 컬렉션(Garbage Collection)은 어떤 Object를 Garbage로 판단해서 스스로 지워버릴까?

= 메서드가 끝나는 등의 특정 이벤트로 Heap영역 객체의 메모리 주소를 가진 참조 변수가 삭제가 되면 Heap 영역에서 어디서도 참조하고 있지 않은 객체들이 발생 ⇒ 이 Object들을 주기적으로 제거


Mark and Sweep - 청소 방식

  1. Mark 과정 - (1) : Garbage Collector가 Stack의 모든 변수를 스캔하면서 각각 어떤 객체를 참고하고 있는지 찾아서 마킹한다.
  2. Mark 과정 - (2) : Reachable Object가 참조하고 있는 객체도 찾아서 마킹한다.
  3. Sweep 과정 : 마킹되지 않은 객체를 Heap 에서 제거한다.
  4. Compact 과정 : Sweep 후에 분산된 객체들을 Heap 의 시작 주소로 모아 메모리가 할당됭 부분과 그렇지 않은 부분으로 압축한다.(종류에 따라 하지 않는 경우도 O)

Garbage Collection 동작 과정

JVM의 Heap 영역은 동적으로 레퍼런스 데이터가 저장되는 공간으로서, GC에 대상이 되는 공간이다.

하나의 Heap 영역을 세부적으로 쪼개 객체의 생존기간을 세밀하게 제어

  • Heap 영역 설계 전제 'weak generational hypothesis’

    • 대부분의 객체는 금방 접근 불가능 상태(Unreachable)가 된다.
    • 오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다.
  • 즉 객체는 대부분 일회성이고, 메모리에 오래 남아있는 경우는 드물다

  • Heap 영역 구분

    • Young Generation : 새로운 객체들이 할당되는 영역
    • Old Generation : Young Generation 오래동안 살아남은 객체들이 존재하는 영역
  • Young Generation에서의 GC

    • 메모리 상의 객체를 찾아 제거하는데 적은 시간이 걸림 ⇒ Young 영역에 대한 GC를 Minor GC라 부름
    • 많은 객체가 Young 영역에서 생성되었다가 사라진다.
    • Eden : 새로 생성된 객체 위치 → GC 이후 살아남은 객체 Survivor 영역으로 이동
    • Survivor 1 / 2 : 최소 1번의 GC 에서 살아남은 객체가 존재 , 둘중 하나는 꼭 비어있어야 한다.
  • Old Generation에서의 GC

    • Young 영역 보다 크게 할당 되고, 영역의 크기가 큰 만큼 오랜시간이 걸린다. (10배 이상)
      ⇒ Stop-The-World 문제 발생
    • Old 영역에 대한 GC를 Major GC 또는 Full GC 라고 부른다.
    • Survivor 에서 객체의 age(살아남은 횟수)가 임계값에 도달하면 Old Generation으로 이동

3. 주요 Garbage Collection 알고리즘

Serial GC

  • 적은 메모리와 CPU 코어 수 가 적을때 사용하기 위해 개발된 가장 단순한 GC
  • 가장 Stop-The-World 시간이 길다.
  • Young 영역에서는 Mark-Sweep 사용하고, Old 영역에서는 Mark-Sweep-Compact을 사용한다.

Parallel GC

  • Java 8 default GC
  • Serial GC와 알고리즘은 동일하지만, Young영역의 Minor GC 멀티 쓰레드로 수행

Parallel Old GC

  • Parallel GC 를 개선해 Old 영역도 멀티 쓰레드로 수행
  • GC 방식을 Mark-Summary-Compact 방식으로 이용

G1 GC (Garbage First)

  • CMS GS(GC 복잡한 과적으로 수행되어 메모리 파편화 문제 발생한 알고리즘 - java14에서부터 사용 중지)
  • CMS GS 대체제로 등장 → java 9+ 버전의 default GC
  • 목적 = 큰 Heap 메모리에서 짧은 GC 시간 보장
  • Heap 영역을 Young/Old 로 구분하지 않고, Region 이라는 개념 도입

  • Region (2048개의 Region)
    • Humongous : Region 크기의 50%를 초과하는 큰 객체를 저장하기 위한 공간이며, 이 Region 에서는 GC 동작이 최적으로 동작하지 않는다.
    • Available/Unused : 아직 사용되지 않은 Region을 의미한다.
    • 각 heap 영역들은 고정이 아닌 동적으로 부여
  • 순차적 이동 X , 더 효율적이라고 생각하는 위치로 객체를 재할당 시킨다.


Shenandoah GC

  • Redhat에서 개발 GC
  • G1 GC의 pause dltb goruf
  • Heap 사이즈에 영향을 받지 않고, 일정한 pause 시간이 소요가 되는것이 특징


참고한 자료

  1. https://www.ibm.com/docs/ko/sdk-java-technology/8?topic=introduction-java-virtual-machine
  2. https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
  3. https://youtu.be/vZRmCbl871I?si=uWo59nmT_92hBy1k
  4. https://www.youtube.com/watch?v=Fe3TVCEJhzo&list=WL&index=4
  5. https://d2.naver.com/helloworld/1329
  6. https://www.itworld.co.kr/news/276625
  7. https://mirinae312.github.io/develop/2018/06/04/jvm_gc.html
profile
success is within reach, allow yourself time

0개의 댓글