참조한 사이트의 영문 번역글입니다.
메모리 관리
GC
- 사용되지 않는 할당된 메모리를 해제 → 메모리 자동 관리
- Mark, Sweep
- Mark : alive = 여전히 참조되어지는 객체들
- Free : not alive = 객체를 메모리에서 해제
- GC 카운팅
JVM의 메모리 관리
Heap Memory
- JVM → 객체, 동적 데이타 저장
- 크기
- 두가지 영역
- Young = new space ← Minor GC가 관리
- Eden space : 새 객체가 만들어진 곳 (새객체 만들면 할당되는 메모리)
- Survivor space : Minor GC에 의해 살아남은 객체가 저장된 곳
- Old = Tenured space ← Major GC가 관리
- minor GC가 살아있는 동안 the maximum tenure threshold에 도달한 객체가 있는 곳
Thread Stacks
- 스택 메모리 공간
- 프로세스의 1개 쓰레드 당 하나의 stack memory
- thread-specific static data
- Xss flag : 스택메모리 제한
- default로 상한선을 가지지 않는 native memory 부분
- 클래스 로더 : 클래스 정의 보관
- Mata Space가 계속 커진다면, OS는 저장된 data를 RAM에서 VM으로 옮길것이고, 애플리케이션의 속도 저하 발생
- 속도저하 발생을 피하기 위해, 한계 설정
- XX:MetaspaceSize , -XX:MaxMetaspaceSize flag
Code Cache
- JIT compiler
- 이미 native format으로 interpreted 될 필요 없다.
- JVM은 native machine code로 interptre 해야만 한다.
Shared Libraries
- OS에 의해 하나의 프로세스당 오직 한번만 로드
- 공유된 라이브러리들을 위한 native code가 사용된 곳을 저장
JVM memory usage (Stack vs Heap)
- frame-block으로 thread의 stack 메모리에 추가된다.
- 모든 함수 호출, 모든 지역변수들(매개변수, 반환값)
- primitive types
- Stack은 Stack Pointer를 통해 Heap 메모리 영역 참조
- Object → Heap에 생성
- static field
- 현재 호출된 함수는 Stack의 최상단 위치
- 함수가 'return' 하면 Stack에서 제거
- main process
- Heap 영역에 객체 완성 (어떤 pointer 없이)
- copy 돼야 pointer에 의해 참조된다.
- Stack은 OS에 의해(JVM이 아닌) 자동적으로 관리
- Heap은 OS에 의해 관리되지 않고, 큰 메모리공간을 가지고서 동적데이터를 다룬다.
- 메모리 관리를 위해 JVM은 garbage collection process 를 통해 Heap을 자동적응로 관리한다.
JVM Memory management: Garbage collection
- JVM은 Heap 메모리를 garbage collection르로 관리한다.
- Stack으로부터 직/간접적으로 더이상 참조되어지지 않는 객체를 메모리에서 해제하여
- 새로운 객체 생성을 위한 공간을 확보한다.
- Garbage collection 책임
- OS로부터 메모리 할당 or OS로 반환
- 애플리케이션을 위해 할당된 메모리 처리
- 애플리케이션에 의해 사용되는 할당된 메모리를 결정
- 애플리케이션에 의해 재사용하기 위해 사용되지 않는 메모리 회수
Mark & Sweep Garbage collection
- JVM
- 별개의 daemon thread를 사용
- garbage collection위해 백그라운드에서 실행
- 프로세스
- Mark & Sweep GC
- Marking
- 첫번째 스텝
- garbage collector 는 사용되거나 사용되지 않는 객체를 식별
- Sweeping
- garbage collector 가 heap을 순회하면서, marked 되지 않는 메모리상에 존재하는 객체 제거, 해당 공간은 free로 marked
- Compacting
- 사용되지 않는 객체들 삭제 후에, 남아있는 객체들은 함께 모이도록 옮겨져서, 새로운 객체를 위한 메모리 할당시 성능을 향상시킨다.
- JDK에 따라서 JVM이 제공하는 GC 알고리즘이 달라진다.
- Throughput
- 애플리케이션 운영 대신 garbage를 수집하면서 보낸 시간은 처리량에 영향
- 이상적으로는 처리량이 높아야 한다.
- Pause-time
- GC에 의해 애플리케이션 실행이 멈춘 기간
- 이상적으로 낮아야 한다.
- Footprint
- 사용된 Heap의 크기
- 이상적으로 낮게 유지되야 한다.
Collectors available as of JDK 11
- Serial Collector
- GC에 single thread 사용
- 작은 데이타를 다루는 애플리케이션에 효율적
- single-processor machines 사용시 적절
- -XX:+UseSerialGC switch
- Parallel Collector
- 높은 처리량 목표로 GC process의 속도향상을 위해 multiple threads 사용
- multi-threaded/multi-processor에서 운영되는 medium ~ large 크기의 데이터를 다루는 애플리케이션에 적절
- -XX:+UseParallelGC switch
- Garbage-First(G1) Collector
- 동시성을 대처하기 위해
- 대량의 메모리를 가진 multi-processor machines과 현대 OS를 default로 사용
- 낮은 Pause-time 과 높은 Throughput
- -XX:+UseG1GC switch
- Z Garbage Collector
- JDK 11에서 도입된 실험적인 GC
- 낮은 대기시간의 collector로 확장 가능하다
- 동시적이고, 애플리케이션의 실행중이던 thread들을 멈추지 않는다.
- 낮은 latency, 매우 큰 heap(multi-terabytes)
- -XX:+UseZGC switch
GC process
- 언제, 어디냐에 따른 GC process의 2가지 타입 - Minor GC, Major GC
- Minor GC
- young generation space
- 실행 조건
- 새로운 객체 할당 위한 Eden space로부터 요청한 메모리를 JVM이 얻을 수 없을때
- Eden memory : 초기화시 비어있는 heap space에서 survivor/tenuered space로 처음으로 채워진다.
- the minor GC process
- Eden space가 채워져 있고, 애플리에케이션에서 새 객체를 생성했을 때
- minor GC
- stack pointer 에서 mark 객체까지 GC가 재귀적으로 순회
- alive 상태로 사용된 객체
- garbage로 남아있는 객체 (Orphans)
- JVM이 S0 또는 S1 중 랜덥하게 선택 (S0라면)
- GC는 alive Object들을 S0로 옮긴다. : S0 → "To Space"
- 옮겨진 Object들의 age 1씩 증가
- 비워진 Eden 공간으로 새 객체 할당
- 일정 시간이 지난후, Eden space에 더 낳은 객체들로 채워져 있을 때 애플리케이션이 새 객체 생성
- JVM triggers a second minor GC
- GC의 Marking 스텝 반복
- survivor 공간의 S0 까지 alive/orphan objects 들을 mark
- 이번엔 JVM이 비어있는 S1을 선택 (기존에 랜덤하게 S0 썼다면)
- S1 → "To Space", S0 → "From Space"
- GC는 Eden space와 S0의 alive 객체들을 S1으로 옮긴다.
- 몇몇 객체들의 age가 "max-age threshold"(15 by default) 도달했다면, Tenured space 로 옮겨진다.
- Major GC
- the old generation(Tenured) space 유지
- Major GC 실행 조건
- System.gc(), or Runtime.getRunTime().gc() 호출시
- minor GC cycles에 의해 채워지기 위한 tenured space 가 충분하지 않을 때 JVM이 결정에 의해 실행
- JVM이 Eden space나 survivor spaces로부터 메모리를 복구할 수 없을때
- JVM의 MaxMetaspaceSize 옵션 설정으로 새로운 클래스가 로드될 공간이 부족할 때
공부해야 할 내용들이 정말 많네요 ㅠㅠ 좋은 글 감사합니다 👍