[Programming Language] Java Garbage Collection

Sunwu Park·2024년 5월 26일

ProgrammingLanguage

목록 보기
1/1

접근 불가능?

  • 더 이상 해당 객체를 참조하는 변수나 데이터 구조가 없어서 프로그램 내에서 해당 객체를 사용할 수 없게 된 상태
HotSpot VM에서의 방식

HotSpot=JVM

JVM에서는 두가지의 영역으로 나누었다

  • Young 영역:
    - 새롭게 생성한 객체의 대부분이 여기에 위치
    - 대부분의 객체가 금방 접근 불가 => 많은 객체가 Young 영역에 생성되었다가 사라진다!
    - 객체가 사라지면 => Minor GC

  • Old 영역
    - 접근 불가능 상태로 되지 않아 Young 영역에서 살아남은 객체가 여기로 복사
    - Young보다 크게 할당
    - GC적게 발생
    - 객체가 사라지면 => Major GC(Full GC)

    - Permanent Generation 영역은 Method Area라고 한다
    - 객체나 억류된 문자열 정보 저장? 
    - 영원히 남아있는 것은 아님 => GC발생(Major)

Card Table?

  • Old 영역의 객체가 Young 영역의 객체를 참조할때 정보 표시 => Young 영역의 GC를 실행할때 Old영역의 모든 객체를 참조하지 않고 이 테이블만 뒤져서 GC대상인지 식별
  • [[write barrier]]방법!

Young 영역의 구성

  • [[Eden]] 영역
  • Survivor 영역(2개)
  • => 총 3개의 영역으로 나뉘는 것이다!

Copy & Scavenge

절차:
1. Eden 영역은 자바 객체가 생성되자마자 저장되는 곳이다. 이렇게 생성된 객체는 Minor GC가 발생할 때 Survivor 영역으로 이동하게 된다.
2. Survivor 영역은 Survivor1과 Survivor2 두 영역으로 나뉘는데, Minor GC가 발생하면 Eden과 Survivor1에 활성 객체를 Survivor2로 복사한다.
3. 활성이 아닌 객체는 자연스럽게 Survivor1에 남아있게 되고, Survivor1과 Eden 영역을 클리어 한다. (결과적으로 활성 객체만 Survivor2)로 이동하게 된 것이다.
4. 다음번 Minor GC가 발생하면 같은 원리로 Eden과 Survivor2 영역에서 활성 객체를 Survivor1으로 이동시키게 된다. 계속 이런 방식을 반복하면서 Minor GC를 수행한다.
5. 이렇게 Minor GC를 수행하다가 Survivor 영역에서 오래된 객체는 Old 영역으로 옮기게 된다.

JVM에서는 빠른 메모리 할당을 위해 두가지 기술을 사용한다
1. bump-the-pointer 기술
1. Eden영역의 마지막 객체를 추적(top)
2. 크기가 적당한지 판정 => 넣는다
3. 마지막에 추가된 객체만 점검함으로써 빠르게 메모리를 할당한다
4. 멀티쓰레드에서 사용하는 여러 객체를 Eden영역에 저장하려면 락이 발생 => TLABs로 해결
2. TLABs(Thread-Local Allocation Buffers)
1. 각각의 스레드가 각각의 몫에 해당하는 Eden 영역의 작은 덩어리를 가지게 한다
2. 각 쓰레드는 자신의 TLAB에만 접근하므로 락 없이 할당 가능
3.

Old 영역에 대한 GC

알고리즘: Mark-Sweep-Compaction
객체들의 참조를 확인하면서 참조가 연결되지 않은 객체를 표시! 작업이 끝나면 삭제
- 속도가 매우 느리다! Stop-the-world현상이 일어난다!

  1. Serial GC

    1. Old영역의 GC는 Mark-Sweep-Compaction
    2. Old영역에 살아있는 객체를 식별(Mark)한 뒤 Heap의 앞부분부터 확인하며 살아 있는 것만 남긴다(Sweep). 각 객체들이 연속되게 쌓이도록 힙의 가장 앞 부분부터 채운다(Compaction)
  2. Parallel GC

    1. 처리하는 쓰레드가 여러 개

    종류:

    • Low-Pause
      - GC가 일어날때 애플리케이션이 멈추는 현상을 최소화하는데 역점을 두었다
    • [[Throughput방식]]
      - Minor GC가 발생하였을 때 되도록이면 신속하게 수행하도록 throughput에 중점을 두었다.
      - ![[Pasted image 20240523021409.png]]
  3. Concurrent GC (ConcurrentMarkSweep GC)

    1. Stop-the-world 최소화

    2. 일부는 애플리케이션이 돌아가는 단계에서 수행하고 최소한의 작업만을 애플리케이션이 멈췄을 때 수행하는 방식이다.

      1. 초기 initial Mark단계에서 가장 가까운 객체중 살아 있는 개체만 찾는다 => 멈추는 시간이 굉장히 짧다
      2. Concurrent Mark단계에서 살아있다고 확인한 객체 참조하는 객체 따라가서 확인
      3. Remark => 앞의 단계에서 새로 추가되거나 참조가 끊긴 객체 확인
      4. 마지막 Concurrent Sweep단계에서 쓰레기 정리
        => Concurrent Mark & Concurrent Sweep에서는 다른 스레드가 실행되는 상황에서 진행한다!!!!
      • 하지만 다른 GC방식보다 메모리와 CPU를 더 많이 사용
      • Compaction단계가 기본적으로 제공되지 않는다!!!
  1. Incremental GC (Train GC)

    1. Minor GC가 일어날 때마다 Old 영역을 조금씩 GC 해서 Full GC가 발생하는 횟수나 시간을 줄이는 방식
    2. 하지만 자원을 많이 소모 + Minor GC를 자주 일으킴 => 오히려 느릴 수도?
  2. Garbage First(G1 GC)
    1. G1 GC는 바둑판의 각 영역에 객체를 할당하고 GC를 실행한다.
    2. 그러다가, 해당 영역이 꽉 차면 다른 영역에서 객체를 할당하고 GC를 실행한다.
    3. 즉, 지금까지 설명한 Young의 세가지 영역에서 데이터가 Old 영역으로 이동하는 단계가 사라진 GC 방식이라고 이해하면 된다

    		사이클중 모든 원은 stop-the-world가 발생한 것을 나타낸 것이고, 원의 크기에 따라 소요 시간이 달라진다고 보면 된다.
    		파란 원은 Minor GC(=Young GC, Evacuation Phuse)가 진행함에따라 stop-the-world가 발생한 것이다.
    		주황 원은 Major GC(=Old GC, ConcurrentCycle)이 진행하면서 객체를 마킹 및 기타 과정을 하기 위해 stop-the-world가 발생한 것이다.
    		빨간 원은 Mixed GC를 진행함에 따라 stop-the-world가 발생한 것이다.
    		https://youn0111.tistory.com/67

자바 GC로그 모니터링

  • 자바 옵션에 -verbosegc 라는 옵션을 주면 되고, > 리다이렉션 명령어를 통해서 파일로 저장하고 분석할 수 있다.
java -jar -verbosegc app.jar

https://youn0111.tistory.com/67

0개의 댓글