JVM 메모리 관리

sally·2022년 1월 17일
1

JAVA

목록 보기
1/4

참조한 사이트의 영문 번역글입니다.

메모리 관리

GC

  • 사용되지 않는 할당된 메모리를 해제 → 메모리 자동 관리
  • Mark, Sweep
    • Mark : alive = 여전히 참조되어지는 객체들
    • Free : not alive = 객체를 메모리에서 해제
  • GC 카운팅
    • 객체마다 참조 카운트를 얻는다.
      • 참조의 증감 → 0 → GC 수행


JVM의 메모리 관리

Heap Memory

  • JVM → 객체, 동적 데이타 저장
    • GC : 메모리에서 가장 큰 block 차지
  • 크기
    • initail ~ Max flags
  • 두가지 영역
    • Young = new space ← Minor GC가 관리
      • Eden space : 새 객체가 만들어진 곳 (새객체 만들면 할당되는 메모리)
      • Survivor space : Minor GC에 의해 살아남은 객체가 저장된 곳
        • S0
        • S1
    • Old = Tenured space ← Major GC가 관리
      • minor GC가 살아있는 동안 the maximum tenure threshold에 도달한 객체가 있는 곳

Thread Stacks

  • 스택 메모리 공간
    • 프로세스의 1개 쓰레드 당 하나의 stack memory
  • thread-specific static data
    • 메서드(함수) 프레임, 객체의 포인터 보관
  • Xss flag : 스택메모리 제한

Meta Space

  • 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
          1. stack pointer 에서 mark 객체까지 GC가 재귀적으로 순회
            • alive 상태로 사용된 객체
            • garbage로 남아있는 객체 (Orphans)
            • JVM이 S0 또는 S1 중 랜덥하게 선택 (S0라면)
              • GC는 alive Object들을 S0로 옮긴다. : S0 → "To Space"
              • 옮겨진 Object들의 age 1씩 증가
            • 비워진 Eden 공간으로 새 객체 할당
          2. 일정 시간이 지난후, 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 1씩 증가
              • 몇몇 객체들의 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 옵션 설정으로 새로운 클래스가 로드될 공간이 부족할 때
profile
sally의 법칙을 따르는 bug Duck

2개의 댓글

comment-user-thumbnail
2022년 1월 18일

공부해야 할 내용들이 정말 많네요 ㅠㅠ 좋은 글 감사합니다 👍

1개의 답글