자바 JVM

Heap영역 vs Native영역

  • 힙영역에 해당하는건 Runtime Data Area중에 힙영역 뿐이다
    • Image for post
  • 즉, 내가 본 이미지중 Runtime Data Areas의 가장 정확한 표현은6
    • Java Virtual Machine Changes in Java 7,8 and 9
    • 위의 이미지가 아닐까.
  • JDK 8에서 Perm 영역은 왜 삭제됐을까

  • D2 - Java Garbage Collection

  • D2 - JVM Internal
  • D2 - Java Reference와 GC

  • GC이후엔 Compaction과 같은 알고리즘을 통해 단편화된 메모리 영역을 합치는 작업을 한다.
    • 아래 그림이 compaction의 필요성을 잘 보여준다. https://engineering.linecorp.com/en/blog/go-gc/
    • non-moving
    • moving
  • GC의 2가지 가설(경험적 지식에 의한)
    • 대부분의 object는 생성된 후에 금방 garbage가 된다.
      • 첫번째 가설에 따르면 young영역은 fragmentation발생 확률이 높다.
      • 따라서 compaction과 같은 비싼작업을 자주 해야한다.
      • 그래서 garbage가 될 확률이 적은 객체들을 따로 관리하는게 유용하다. (파편화를 최소화)
      • 이를 위해 전용공간인 eden영역을 따로 만들고, 살아있는 객체를 피신시킬 survivor 공간을 별도로 두었다. (따로 관리)
    • Old object가 young object를 참조할일은 드물다.
      • Garbage추적에 사용하는 Tracing 알고리즘
        • Tracing알고리즘 : Root Set에서 참조하는 객체들을 마킹해 나가는 방법
        • 위 작업은 memory suspended인 상황에서 수행되기 때문에, 서비스가 suspended된 시간을 줄이기 위해 young generation 영역 한정으로 수행된다
          • (old obejct가 young object를 참조할 일이 있다고 가정할 경우, 전체 heap을 체크해야 하고, 그만큼 suspended시간이 길어짐)
        • Old -> young을 참조하는 경우는 card table이라는 보완책을 사용한다. ( old object의 맨앞에 young을 참조하는지 여부의 flag를 두고, flag만 확인한다.)
  • GC의 대상 및 범위는 3가지로 분류가능
    • Young영역의 Minor GC
      • Eden, Survivor 영역의 Live Object Copy 작업
      • 빈번하게 발생 (Eden영역 full, Survivor 영역 full)
        • survivor영역 몇% 찼을때 minor gc를 일으킬 것인지 : -XX:TargetSurvivorRatio={default 50} 로 설정가능
      • 성숙된 object(참조 횟수 기준)는 old영역으로 이동됨
        • old영역으로 보내는 기준이 되는 참조 횟수
    • Old 영역의 Full GC(Major GC)
      • old영역으로 object를 이동하는중 old영역의 메모리가 충분하지 않으면 gc일어남
    • Permanent Area가 부족할때 Full GC
      • 너무 많은수의 class가 로딩되어 공간이 없을경우에 해당함
      • perm영역의 공간이 부족하면, heap공간(young + old)에 용량이 많더라도 full GC가 발생
  • GC 관련 옵션

    • Java Memory Model!
    • http://wiki.gurubee.net/pages/viewpage.action?pageId=34603019

    • 많이 경험한 옵션들 (Server 옵션기준)

      • SurvivorRatio : eden : survivor1 : survivor2 를 n:1:1로 설정함 (default=8)

      • NewRatio : young:old비율을 1:n으로 설정함 (default=2)

      • -Xms , -Xmx

        • 최소, 최대 메모리 크기

        • 보통 같게 설정 (memory 크기를 동적으로 늘리거나 줄이는건 성능에 큰 영향을 주기 떄문)

        • default 설정으로는, 전체 heap 대비 free Space가 40% 이하이면 -Xmx까지 늘리고, free Space가 70% 이상이면 -Xms까지 축소한다

    • 많이 경험 하지 않은 옵션 중에 유의미해 보이는 옵션들
      • -XX:ThreadStackSize={512}
      • -XX:TargetSurvivorRatio={default 50}
      • survivor 영역이 몇 % 찼을때 minor gc를 유발할 것인지
      • 높게 지정시 Survivor area의 활용도가 높아져서 minor GC빈도를 낮출 수 있다.
      • -XX:MaxTenuringThreshold={value}
      • Minor gc 를 몇번동안 살아남은후에 old 영역으로 promotion될지
      • 즉, 0일경우 eden 영역에서 1회 minor gc이후 바로 old영역으로 넘어가게된다.
      • https://support.oracle.com/knowledge/Middleware/1283267_1.html
    • 기타
      • -X는 Marco한 측면, -XX는 Micro한 측면의 제어를 위해 사용함.
      • -XX:+ / -XX:- : +와 -는 옵션을 켜고 끌때 사용함(boolean)
        • ex) -XX:+UseParallelGC

Garbage Collector 종류

  • 가장 큰 이슈는 GC의 Suspended 현상
name Young Generation Collection 알고리즘 Old Generation Collection 알고리즘 설명
Serial GC Serial Serial Mark-Sweep-Compact (한개의 쓰레드가 수행)
Parallel GC Parallel Copy Serial Mark-Sweep-Compact 모든 자원을 투입해서 GC를 빨리 끝내는 전략
(대용량 Heap에 적합하다)
Parallel Compacting GC Parallel Copy Parallel Mark-Sweep-Compact  
CMS GC Parallel Copy Concurrent Mark-Sweep Suspended Time을 분산시켜 체감 pause를 줄인다.
G1 GC Snapshot-At-The-Beginning(SATB) Snapshot-At-The-Beginning(SATB) Generation을 물리적으로 구분하지 않고 Region 단위로 쪼개서 관리함
  • Serial GC
    • 1개의 Thread를 가지고 GC를 수행한다
  • Parallel GC
    • young 영역에서의 GC를 병렬로 수행함
    • suspended상태를 최소화 시키는 것이 목적
    • PLAB(Parallel Allocation Buffer)라는 Promotion Buffer를 통해 여러 쓰레드간 동시성 문제를 회피한다.
      • Promotion할 Old영역을 쓰레드별로 따로 분배해주는 방식
  • CMS GC
    • Suspended Time을 분한하여, Pause Time을 줄이는 방식
    • 힙 영역이 클때 적합함. low-latency collector로도 알려져있음
    • Old 영역에서Concurrent Mark-Sweep 알고리즘 사용
      • Initial MarkPhase -> Concurrent Mark Phase -> Remark Mark Phase -> Concurrent Sweep Phase 단계로 수행된다.
        • 이때 어플리케이션이 중지되는 단계는 1,3 단계뿐임
      • Concurrent Sweep Phase
        • 한 쓰레드 가지고 garbage로 판명된 객체들을 지워간다
        • Compaction작업을 수행하지 않기때문에 Suspended가 일어나지 않는다.
        • 대신 Free List를 통해 단편화를 줄이는 노력을 한다.
          • Free List : Old영역의 Free Space의 정보를 관리함. promotion되는 object와 사이즈가 유사한 space를 찾아준다.(혹은 free Space를 적절하게 붙여서 영역을 제공하기도 함)
          • Compaction을 하지 않는 대신 개별 object를 old영역에 Allocation할때의 시간이 더 길어짐.(compaction을 할경우, 그냥 순서대로 할당하면 되서 Allocation이 빠르다.)
          • Promotion이 빈번하지 않을경우 유리한 점이 있다.
  • G1 GC
    • young/old 구분을 없애고 전체 HEAP을 1Mbytes의 Region으로 재편함
    • Mark 단계에서 최소한의 suspended 시간으로 garbage들을 골라낸다 ( parallel compaction gc 처럼)
    • Region별로 순차작업을 하기위해 Remember Set을 이용한다.
    • Garbage First : Garbage로 가득찬 Region부터 gc 수행(발견되자마자 즉각 수행)
    • Garbage가 대부분인 Region의 경우 다른 Region으로 live Object을 compaction함
      • G1 GC에서는, Young/Old가 물리적 개념이 아니고, Object가

왜 minor는 stop-the-world가 안일어나고, major gc는 일어나는거지?