[Java] About JVM
by Push's tone
자바 JVM
Heap영역 vs Native영역
- 힙영역에 해당하는건 Runtime Data Area중에 힙영역 뿐이다
- 즉, 내가 본 이미지중 Runtime Data Areas의 가장 정확한 표현은6
- 위의 이미지가 아닐까.
- D2 - JVM Internal
- GC이후엔 Compaction과 같은 알고리즘을 통해 단편화된 메모리 영역을 합치는 작업을 한다.
- 아래 그림이 compaction의 필요성을 잘 보여준다. https://engineering.linecorp.com/en/blog/go-gc/
- 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만 확인한다.)
- Garbage추적에 사용하는 Tracing 알고리즘
- 대부분의 object는 생성된 후에 금방 garbage가 된다.
- GC의 대상 및 범위는 3가지로 분류가능
- Young영역의 Minor GC
- Eden, Survivor 영역의 Live Object Copy 작업
- 빈번하게 발생 (Eden영역 full, Survivor 영역 full)
- survivor영역 몇% 찼을때 minor gc를 일으킬 것인지 :
-XX:TargetSurvivorRatio={default 50}
로 설정가능
- survivor영역 몇% 찼을때 minor gc를 일으킬 것인지 :
- 성숙된 object(참조 횟수 기준)는 old영역으로 이동됨
- old영역으로 보내는 기준이 되는 참조 횟수
- Old 영역의 Full GC(Major GC)
- old영역으로 object를 이동하는중 old영역의 메모리가 충분하지 않으면 gc일어남
- Permanent Area가 부족할때 Full GC
- 너무 많은수의 class가 로딩되어 공간이 없을경우에 해당함
- perm영역의 공간이 부족하면, heap공간(young + old)에 용량이 많더라도 full GC가 발생
- Young영역의 Minor GC
-
GC 관련 옵션
-
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}
- 스택 사이즈의 영향 (StackOverflow vs OOME(by 스택크기로 인한)java의-stack-size에-대해
- -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
- -XX:ThreadStackSize={512}
- 기타
- -X는 Marco한 측면, -XX는 Micro한 측면의 제어를 위해 사용함.
-XX:+
/-XX:-
: +와 -는 옵션을 켜고 끌때 사용함(boolean)- ex)
-XX:+UseParallelGC
- ex)
-
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이 빈번하지 않을경우 유리한 점이 있다.
- Initial MarkPhase -> Concurrent Mark Phase -> Remark Mark Phase -> Concurrent Sweep Phase 단계로 수행된다.
- 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는 일어나는거지?
Subscribe via RSS