kok202
GC

2020. 4. 25. 01:54[정리] 기능별 개념 정리/JVM

GC

자바에서는 메모리를 GC 알고리즘을 통해서 관리한다.

따라서 개발자가 메모리 처리 로직을 만들 필요도 없고 만들어서도 안된다.

GC 는 런타임 데이터 영역중 Heap 영역이 대상이 된다.

GC 가 제대로 동작하지 않으면 메모리가 가득차서 JVM Hang 이 걸리거나 메모리를 추가할당 받게된다.

메모리를 계속 추가 할당 받다가 넘치게되면 OutOfMemory 로 JVM 이 다운될 수 도 있다.

GC 가 발생하거나 객체가 이동할 때마다 어플리케이션에 병목이 발생하고 성능에 영향을 준다.

JVM 에서는 이를 관리하기 위해 스레드 로컬 할당 버퍼라는 것을 이용한다.

이는 스레드 별로 메모리 버퍼를 사용하여 다른 스레드에 영향을 주지 않는 메모리 할당 작업을 가능하게한다.

 

 

 

GC 의 목표

  • 메모리 할당
  • 사용중인 메모리 인식
  • 사용하지 않는 메모리 인식

GC 는 도달 불가능한 객체를 파악하고 이를 제거하게된다.

이 과정에서 Mark and sweep 이라는 과정을 거치게된다.

 

 

 

자바의 메모리 영역

  1. Young
    1. Eden
    2. Survivor1
    3. Survivor2
  2. Old

Perm 영역이 존재했었으나 JDK 8 부터 사라졌다.

Young 영역에서 발생하는 GC 를 minor GC 라고한다.

Old 영역에서 발생하는 GC 를 major GC 라고한다.

Young, Old 영역에서 발생하는 GC 를 full GC 라고한다.

 

 

 

Stop the world (STW)

GC 가 동작하는 동안 자바 어플리케이션이 멈추는 현상

일반적인 통념으로는 Major GC 에서만 STW 가 발생한다고 알려져있으나 실제는 그렇지 않다고 한다.

Against common belief, all Minor GCs do trigger stop-the-world pauses, stopping the application threads.

출처 : https://plumbr.io/handbook/garbage-collection-in-java/minor-gc-major-gc-full-gc

 

 

 

GC 의 기본동작 원리

  1. 객체가 생성되면 Eden 에 저장된다.
  2. Eden 이 가득차면 Survivor 1이나 2 둘중 아무 영역으로 이동한다. (Minor GC)
  3. Survivor 영역은 반드시 둘 중 한 영역은 비어있어야한다.
  4. Minor GC 가 발생할 때마다 상대편 Survivor 영역으로 객체가 왔다 갔다 이동한다. 이렇게 이동하면서 객체들의 age bit 가 증가한다.
  5. age bit 가 계속 증가하다 보면 특정 age 이상은 Old 영역으로 이동하게된다. 이를 Promotion 이라고한다.
  6. 이렇게 이동한 Old 영역에서 GC 가 발생할 경우 이를 Major GC 라고 한다. Major GC 영역에서 GC 알고리즘은 다양하며 이로인한 다양한 GC 방식들이 존재한다.

Young 영역에서 Old 영역으로 넘어가는 객체 중 Survivor 를 거치지 않는 경우가 있다. 

예를들어 Survivor 영역의 크기보다 객체의 크기가 큰 경우가 그렇다.

 

 

 

GC 의 5가지 방식

  1. Serial Collector
    Minor GC 과정에서 객체의 영역을 옮기는 과정을 직렬로 처리한다. 
    Major GC 과정에서 Mark sweep compact 알고리즘을 사용한다.

    사용하지 말아라
  2. Parallel Collector
    Minor GC 과정을 객체의 영역을 옮기는 과정을 병렬로 처리한다.
    Major GC 과정에서 Mark sweep compact 알고리즘을 사용한다.
  3. Parallel Compacting Collector
    Minor GC 과정을 객체의 영역을 옮기는 과정을 병렬로 처리한다.
    Major GC 과정에서 Mark summary compact 알고리즘을 사용한다.
  4. CMS Collector
    Minor GC 과정을 객체의 영역을 옮기는 과정을 병렬로 처리한다.
    Major GC 과정에서 Concurrent mark sweep 알고리즘을 사용한다.

    힙메모리 영역의 크기가 클때 적합하다.
    Stop the world 시간이 짧다.
    Concurrent mark sweep 알고리즘으로 인해 단편화 문제가 발생한다.
  5. G1 Collector
    Minor GC 과정을 객체의 영역을 옮기는 과정을 병렬로 처리한다.
    Major GC 과정에서 G1 알고리즘을 사용한다.

    Heap 영역을 Linear 하게 사용하던 이전과 다르게 사용하는 방법이다.
    Heap 영역을 거대한 바둑판 배열로 보고 한칸한칸을 Region이라고 부른다.
    Region 이 각각 Eden, Survivor, Old 영역을 역할 변경하면서 사용된다.
    힙메모리가 4GB 이상일 때 사용가능하다. 
    Stop the world 시간을 대략적으로 설정할 수 있다.
    CMS 의 단편화 문제를 해결한다.

 

 

 

Major GC 알고리즘

  1. Mark sweep compact 알고리즘
    특징 : 단일 스레드로 동작한다.
    1. 쓰이는 객체를 마킹한다.
    2. 쓰이지 않는 객체를 삭제한다.
    3. 객체를 삭제하면서 생긴 메모리 파편화를 정리한다.
  2. Mark summary compact 알고리즘
    특징 : 멀티 스레드로 진행된다. Heap 영역을 Region 으로 나누고 Region 별로 스레드가 할당된다.
    1. Old 영역을 Region 으로 나누고 쓰이는 객체를 마킹한다.
    2. Region 의 도달 가능한 객체의 밀도를 조사하고 GC 의 수행범위를 정한다.
    3. 객체를 삭제하면서 생긴 메모리 파편화를 정리한다
  3. Concurrent Mark Sweep (=Tri-color-marking)
    특징 : Compaction 과정을 거치지 않는다. 그러므로 단편화 문제가 있다.
    단편화가 너무 심해져서 메모리 사용이 어려울 때 Compaction 이 발생한다. 따라서 이 때의 Compaction 과정은 STW가 오래 걸린다.
    1. Initial mark : GC 루트에서 가장 가까운 살아있는 객체를 마킹한다. (STW o, 싱글 스레드로 처리한다.)
    2. Concurrent mark : 이전 단계에서 마킹한 객체가 참고하는 객체를 찾는다. (STW x)
    3. Remark : 이전 단계에서 마킹하는 동안 변경된 객체를 다시 마킹한다. (STW o, 멀티 스레드)
    4. Concurrent Sweep : 쓰이지 않는 객체를 제거한다.
  4. G1 GC 알고리즘
    1. Initial mark : Old 영역의 객체가 Survivor 영역의 객체를 참조하고 있는 객체들을 마킹한다.  (STW o)
    2. Root region scan: 이전 단계에서 마킹한 객체가 있는 region 을 스캔한다.
    3. Concurrent global mark : Heap 영역 전체에서 살아있는 객체를 마킹, 죽은 객체만 있는 구역은 정리한다. (STW o)
    4. Remark : SATB 알고리즘을 사용하여 살아있는 객체 마킹 작업을 완료한다.(STW)
    5. Cleanup : 살아있는 객체 작은 구역부터 제거, 제거후 비어있는 구역을 여유 목록에 추가 (STW)
    6. Copy : 살아있는 객체를 비어있는 구역으로 모은다.

 

 

 

GC 모니터

  • jstat CUI 애플리케이션
    로깅에 한계가 있다. 로그를 남기는 주기에 GC 가 몇번 발생할 수 있을지 모르기 때문이다.
    -gcutil : 힙 영역의 사용률을 알려준다.
    -gccapacity : 현재 각 영영에 할당된 메모리 크기를 KB 로 나타낸다.
  • jstated
    원격 모니터링
    단 자바의 기본 보안 옵션이 리모트 객체를 만드는 것을 막고 있기 때문에 security/java.policy 에서 추가 작업을 해줘야한다.
  • verbosegc
    JVM 가동 시점에 -verbosegc 옵션 줘서 사용한다.
  • jconsole
  • jvisualvm
  • Visual GC

 

 

 

jps (Java PS)

현재 실행중인 자바 인스턴스 확인 자바 인스턴스를 확인할 수 있는 명령어다.

 

 

 

메모리 릭

FullGC 수행이후 Old 영역이 80% 이상이라면 메모리 릭을 의심해볼 수 있다.

 

 

 

GC 튜닝은 항상 할 필요가 없다.

GC 튜닝을 해야하는 경우

1. -Xms 혹은 -Xmx 로 메모리 크기를 지정하지 않았다.

2. -server 옵션이 포함되어있지 않다.

3. 시스템에 Timeout 로그가 남는다.

GC 시간이 1초도 되지않는다면 굳이 할 필요가 없다.

GC 튜닝은 가장 마지막에 하는 작업이다. 객체의 생성을 줄이는게 우선이다.

GC 튜닝시 시간만 보지말고 횟수도 보아야한다.

 

 

 

읽어보면 좋은 포스팅

https://d2.naver.com/helloworld/6043

https://d2.naver.com/helloworld/37111

https://perfectacle.github.io/2019/05/11/jvm-gc-advanced/

 

 

 

 

'[정리] 기능별 개념 정리 > JVM' 카테고리의 다른 글

JVM 의 실행, 종료, 클래스 로더, 아키텍쳐  (0) 2020.04.23
JIT 컴파일러  (0) 2020.04.22
Garbage collection 요약  (0) 2020.03.17