ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] Garbage Collection
    Programming/Java 2024. 2. 28. 01:36
    728x90

    GC

    JVM내에서 메모리 관리를 해주는 것.

    쓰지 않는 객체(힙 메모리 객체가 null)인 경우 가비지 컬렉터의 대상이 된다.

    사용자가 동적으로 생성한 객체가 있는 영역인 Heap메모리에서 동작한다.

     

    C++에서는 Heap영역의 메모리를 사용하기 위해 동적 메모리 영역을 할당 받고 해제하는 과정을 개발자가 직접 해야한다(메모리를 수동으로 직접 관리)

    → 메모리 영역을 할당 받고 해제하지 않으면 메모리 누수가 발생할 수 있고, 이미 해제한 메모리 영역을 또 해제하면 에러가 발생할 수 있다.

    → Java에서는 동적 메모리 영역(힙 메모리)를 GC가 관리하여 에러 발생 요인을 방지할 수 있다.

    GC를 수행하게 되면 GC를 수행하는 스레드를 제외한 모든 스레드가 중지된다.

    → 이것을 stop-the-world라고 한다.

     

    GC 튜닝은 stop-the-world시간을 줄이는 것을 의미한다.

     

    GC가 자주 호출되면 그 만큼 stop the world가 자주 발생하여 사용자 입장에서 느껴질 정도로 애플리케이션 동작이 지연될 수 있다.

     

    Java플랫폼에서는 4가지의 가비지 컬렌션이 지원되는데, Serial GC( 직렬 GC)를 제외하고는 병렬화하여 성능을 향상시킨다.

     

    가비지 컬렉션을 수행하는 오버헤드를 가능한 낮게 유지하는 것이 매우 중요한다.

    → 소규모 시스템에서는 문제가 되지 않을 수 있지만, 대규모 시스템에서는 병목 현상이 발생할 수 있다.

     

    JVM Generations

    모든 객체가 쓰레기인지 검사하는 방식의 가비지 컬렉션은 규모가 큰 프로그램에서 심각한 문제가 생길 수 있다.

    → 따라서 매번 전체를 검사하지 않고 일부만 검사할 수 있도록 Generational한 구조를 고안해 냈다.

    • young generation
      • 객체가 생성되면 이 영역에 위치한다.
      • 이곳이 가득차면 minor gc가 발생한다.
      • minor gc가 발생하면 살아있는 객체들만 체크하고 나머지는 다 없애버린다.
      • null객체는 매우 빠르게 수거 된다. → 살아남은 객체들 중 더 오래 쓸 것 같은 일부 객체는 Old Generation(Tenured)으로 이동합니다.
    • Old Generation(tenured)
      • 이곳이 가득 차면 major gc가 발생한다.
      • major gc는 minor gc보다 더 오래 걸린다.
      • Young Generation는 임계값이 설정되어 있으며, 해당 임계값에 도달하면 오브젝트(객체)는 Old Generation으로 이동한다.
      • major gc는 모든 라이브러리 객체를 포함하기 때문에 속도가 훨씬 느려진다.major gc를 위한 stop the world event 기간(수행 시간)은 Old Generation에 사용되는 GC종류에 영향을 받는다.
      • 따라서 major gc를 최소화해야 한다.
    • Meta space(Permanet Generation )
      • 애플리케이션에서 사용되는 클래스 및 메서드를 설명하는데 필요한 메타데이터가 포함되어 있다.
      • 애플리케이션에서 사용 중인 클래스를 기반으로 런타임에 JVM에 의해 채워진다. Java SE라이브러리 클래스 및 메서드가 여기 저장된다.
      • perm영역이 현재 meta space로 변경되었다.
    구분 Perm Meta Space
    저장 정보 클래스 meta, 메소드 meta, static 변수, 상수 클래스 meta, 메소드 meta
    관리 포인트 Heap 영역 튜닝 + Perm영역 별도 Native 영역 동적 조정
    GC Major GC Major GC
    메모리 측면 -XX : PermSize
    -XX : MaxPermSize
    -XX : MetaSpaceSize
    -XX : MaxMetaspaceSize

    출처 : https://medium.com/luizalabs/java-garbage-collector-porque-precisamos-conhec%C3%AA-lo-9d26ebb0a6d8

    • Stop the World Event
      • 모든 minor gc, major gc는 stop the world 이벤트를 가진다.
      • GC를 수행하게 되면 GC를 수행하는 스레드를 제외한 모든 스레드가 중지된다
      • → 이것을 stop-the-world라고 한다.

     

    Aging Process

    JVM에서 오브젝트(객체) 할당 및 에이징 프로세스

     

    1.모든 new object가 에덴 공간에 할당된다. 2개의 survivor공간은 모두 비어있다.


    2.에덴 공간이 가득 차면 minor gc가 트리거된다.


    3.참조된 객체는 첫 번째 survivor 공간으로 이동한다. 참조되지 않은 객체는 에덴 공간이 지워지면 삭제된다.

     


    4.다음 minor gc에서도 에덴 공간과 같은 일이 일어난다.

    참조되지 않은 객체는 삭제되고 참조된 객체는 survivor공간으로 이동한다.

    그러나 이 경우에는 두 번째 survivor공간(s1)으로 이동한다.

    s0의 마지막 minor gc에 있는 객체는 age가 증가하여 s1으로 이동한다.

    살아남은 객체가 모두 s1으로 이동하면 s0과 에덴이 모두 지워진다.

    survivor공간에 age가 다른 객체를 가지게 된다.


    5.다음 minor gc에서도 같은 과정이 반복된다. 하지만 이번에는 survivor 공간이 바뀐다. 참조된 객체는 s0으로 이동한다. 살아남은 객체는 에이징된다. 에덴과 s1이 클리어된다.


    6.minor gc이후, 오래된 객체가 특정 age임계값(age bit)에 도달하면 young에서 old로 승격된다.

    (이 예에서는 임계값이 8)

    Java8에서는 Parallel GC방식 기준으로 age bit가 15가 되면 promotion이 진행된다.


    7. minor gc가 계속 발생하면 객체는 계속해서 old generation영역으로 승격된다.


    8.(따라서 young generation은 모든 과정을 커버할 수 있다. )

    major gc는 공간을 정리하고 압축하는 작업을 old generation에서 수행한다.

    Old Generation이 다 채워지면 major gc가 발생하여 Mark and Sweep 방식을 통해 필요 없는 메모리를 비운다.

     

    Stop the world

    Stop the world의 역할

     

    1. 메모리 파편화

    2. 객체 일관성

    두 가지 관점에서 볼 수 있다.

     

    1. 메모리 파편화

    Memory fragmentation

    컴퓨터 시스템에서 메모리 공간을 할당하고 해제하는 과정에서 발생하는 현상.

     

    메모리 파편화는 외부 파편화, 내부 파편화로 나뉜다.

    ● 외부 파편화

    메모리 공간이 여러 개의 작은 조각으로 나누어져 사용되어, 충분한 공간이 있음에도 불구하고 큰 메모리 블록을 할당할 수 없는 경우를 말한다.

    ●  내부 파편화

    메모리 공간 중 일부가 할당된 후 남는 공간이 발생하는 경우이다.

     

    예를 들어 8byte의 메모리 블록이 할당되었는데 10byte공간으로 할당 받았다면 2byte의 내부 파편화가 발생한다.

    GC관점에서 메모리 파편화를 해결하기 위해 Compaction을 수행해야 한다.

    할당된 메모리를 해제하는 과정에서 메모리 공간이 새로 남는 것을 해결해야 하기 때문에!

    힙 영역 내의 빈 공간들을 큰 블록으로 만들고 다시 이용할 수 있는 상태로 만들어야 하는데 이를 위해 객체를 새로운 주소로 이동시키고 다시 주소를 참조할 수 있게 해줘야 한다. 그렇기 때문에 Stop the world가 필수이다.

     

    2. 객체 일관성

    GC가 발생하는 동안 stop the world가 발생하지 않는다면!

    GC는 더 이상 사용되지 않는 객체를 탐지하고 수집하는 작업을 수행하는데, 이 과정에서 메모리 내의 객체들의 상태가 변경될 수 있고, 다른 스레드가 객체를 참조할 수 있다. → 잘못된 결과나 오류가 발생할 수 있다.

     

    예를 들어 GC가 수집하는 객체를 스레드가 동시에 참조하고, 나중에 다시 호출했을 때 이미 객체는 수집되어서 존재하지 않기 때문에 오류를 발생시킬 수 있다.

     

    또한, 메모리 단편화 문제를 해결하기 위해 Compaction이 발생하여 객체가 이동하는 과정에서 스레드가 전혀 다른 객체 주소를 참조하여 예상 못한 동작을 일으킬 수 있다.

     

    객체 일관성을 유지시키기 위해 stop the world는 매우 중요한 역학을 담당한다.

     

    GC 알고리즘

    Garbage Collector 알고리즘

    1. Reference Counting

    2. Mark and Sweep

    두가지가 있다. 

     

    1. Reference Counting

    Root Space는 스택 변수, 전역 변수 등 heap영역 참조를 가리키고 있는 공간이다.

    이 알고리즘에서 가비지 컬렉터는 메모리에 있는 각 객체에 대한 포인터 수를 카운트로 유지한다.

    객체에 대한 참조가 생성될 때 카운트가 증가하고, 객체가 소멸하면 카운트가 감소한다.

    reference count는 몇 가지 방법으로 해당 객체에 접근할 수 있는지를 말한다.

    reference count가 0이면 해당 객체에 접근할 수 있는 방법이 없다는 뜻이므로 메모리 해제의 대상이 된다.

    출처 :  https://www.startertutorials.com/corejava/garbage-collection.html

     

    reference counting은 순환 참조 문제가 발생할 수 있다.

    Root Space에서 모든 Heap Space의 참조를 끊어도 서로가 참조 중인 객체는 reference count가 1로 유지된다.

    결국 사용하지 않는 메모리 영역이 해제되지 못하고 메모리 누수가 발생한다!!!


    2. Mark and Sweep

    Mark and Sweep알고리즘은 Reference Counting의 순환 참조 문제를 해결할 수 있다.

     

    객체 메모리 할당;
    사용 중인 객체 검색(표시);
    사용하지 않는 객체 해제(스윕);
    조각화 방지(압축).

     

    출처 :  https://betterprogramming.pub/deep-dive-into-garbage-collection-in-javascript-6881610239a

    1. Old영역에 살아있는 객체를 식별(Mark)
    2. 힙의 앞 부분부터 확인하여 살아 있는 것만 남긴다(sweep)
    3. 마지막 단계에서 각 객체들이 연속되게 쌓이도록 힙의 가장 앞 부분부터 채워서 객체가 존재하는 부분과 없는 부분으로 나눈다.(compaction)

    출처 :  https://rebelsky.cs.grinnell.edu/Courses/CS302/99S/Presentations/GC/

    Root Space부터 그래프 순회를 통해 연결된 객체를 찾아내고(Mark), 연결이 끊어진 객체는 지우고(Sweep) 분산되어 있는 메모리를 정렬(Compaction)한다.

    메모리 파편화를 방지하는 Compaction과정이다.

    Root Space부터 연결이 끊긴 순환 참조되는 객체들도 삭제할 수 있다.

     

    Mark And Sweep방식의 단점도 있다.

    객체의 reference count가 0이 되면 지워버리는 reference counting방식과 달리, Mark And Sweep방식은 의도적으로 특정 순간에 GC를 실행해야 한다.

    즉, 어느 순간에 실행 중인 애플리케이션이 GC에게 컴퓨터 리소스를 내어 주어야 한다는 뜻이다.

     

    따라서 애플리케이션의 사용성을 유지하면서 효율적으로 GC를 실행하는 것이 중요하다.

     

    기억! 의도적으로 GC를 실행해야 한다! 애플리케이션과 GC실행이 병행된다!

     

    GC 종류

    Garbage Collector 종류

    출처 : https://medium.com/@ak123aryan/optimizing-java-garbage-collection-choosing-the-right-gc-for-your-application-e28a0fdb84ca

    Serial GC

    운영 서버에서 절대 사용 금지

     

    가장 단순한 방식의 GC로 싱글 스레드(스레드 1개)로 동작한다.

    싱글 스레드로 동작하여 느리고, 그만큼 Stop The World 시간이 다른 GC에 비해 길다.

    (싱글 스레드를 사용해 가비지 컬렉터의 모든 작업을 수행한다 → 느리다)

     

    병렬 컬렉터에 비해 스레드 간 통신 과부하가 없기 때문에 매커니즘은 매우 효율적이만 실행 일시 중지가 길어진다.

     

    CPU코어가 하나만 있을 때 사용하기 위한 방식. 사용 시 애플리케이션 성능이 많이 저하된다.

    멀티 프로세서 하드웨어를 활용할 수 없으므로 처리 코어가 하나만 있는 장비나 데이터 세트가 작은 소프트웨어(약100MB)에 적합하다.

     

    Mark-Sweep-Compact 알고리즘을 사용

    • Young Generation Collection 알고리즘: Serial
    • Old Generation Collection 알고리즘: Serial Mark-Sweep-Compact

     

    Parallel GC

    병렬 GC

    JDK 8버전 기준 기본 GC (default age bit = 15)

    minor gc를 병렬로 수행한다. → gc의 오버헤드를 현저하게 줄일 수 있다.

    멀티 프로세서나 멀티 스레드 하드웨어에서 돌아가는 중대형 규모의 데이터 셋을 다루는 애플리케이션을 위한 gc

    멀티 스레드를 사용한 컬렉션 사용이 Young영역에 국한된다는 점에 주의.

    Young영역의 GC를 멀티 스레드 방식을 사용하기 때문에 Serial GC에 비해 상대적으로 Stop The World가 짧다.

    병렬GC는 스레드 동기화로 인한 오버헤드 때문에 처리 코어가 하나만 있는 환경에서는 직렬만큼 잘 작동하지 않는다.

     

    • Young Generation Collection 알고리즘: Parallel Scavenge
    • Old Generation Collection 알고리즘: Serial Mark-Sweep-Compact

     

    Parallel Old GC

    Parallel GC의 업그레이드 된 버전.

    Java 7 Update 4버전부터는 Parallel GC를 설정해도 Parallel Old GC가 동작한다. Java8의 디폴트 버전은 Parallel Old GC이다.

    Parallel GC는 Young영역에 대해서만 멀티 스레드 방식을 사용했다면 Parallel Old GC는 Old영역까지 멀티스레드 방식을 사용한다.

    Parallel GC의 Old영역 GC알고리즘인 mark-sweep-compact대신 mark-summary-compact알고리즘을 사용한 방식이다.

    summary단계에서는 이미 GC가 수행된 영역에서 별도로 살아있는 객체를 식별한다.

     

    CMS GC

    Concurrent Mark Sweep GC

    Stop The World로 자바 애플리케이션이 멈추는 현상을 줄이고자 만든 GC

    Reacable한 객체를 한번에 찾지 않고 나누어서 찾는 방식을 사용(4 Step으로 나누어짐)

    1. Initial Mark

       GC Root가 참조하는 객체만 마킹 ( Stop The World 발생 )

    2. Concurrent Mark

       참조하는 객체를 따라가며, 지속적으로 마킹 ( Stop The World없이 이루어짐)

    3. Remark

       concurrent mark과정에서 변경된 사항이 없는지 다시 한번 마킹하며 확정하는 과정 (Stop The World 발생)

    4. Concurrent Sweep

       접근할 수 없는 객체를 제거하는 과정(Stop The World없이 이루어짐)

     

    위와 같이 Stop The World가 최대한 덜 발생하도록 하여 자바 애플리케이션이 멈추는 현상을 줄였다.

     

     

    G1 GC

    Garbage First

    Java 9+의 default GC

    현재 GC중 Stop The World의 시간이 제일 짧음

    CMS GC를 개선해서 만든 GC이다.

    Heap을 Region이라는 일정한 부분으로 나누어서 메모리를 관리한다.

    ( G1 GC는 힙을 1MB에서 32MB 범위의 특정 크기의 영역으로 나누는 다른 메모리 관리 개념을 가짐)

    전체 Heap에 대해서 탐색하지 않고 부분적으로 Region단위로 탐색하여, 각각의 Region에만 GC가 발생한다.

     

    이 구조는 GC가 전체 힙을 한 번에 수집하는 것을 피할 수 있다.

     

    애플리케이션의 전체 GC주기가 매우 빈번하거나 시간이 매우 긴 경우 이 기능을 사용하는 것이 좋다.

     

    G1을 제외한 나머지 GC들은 JVM의 영역을 나눠서 힙에서 객체들을 관리한다.

    서버 스타일 컬렉터.

    큰 메모리를 가진 멀티 프로세서 머신을 위한 컬렉터.

    G1 GC만 Generatinal GC가 아니라는 점에 주의.

    • Young Generation Collection 알고리즘: Snapshot-At-The-Beginning(SATB)
    • Old Generation Collection 알고리즘: Snapshot-At-The-Beginning(SATB)

     

    ▷ G1은 물리적 generation 구분을 없애고, 전체 heap을 1MB 단위의 리전(region)들로 다룬다.

    ▷ G1 이라는 이름은 가비지로 가득찬 리전부터 컬렉션을 시작한다는 의미.  

    가비지로 꽉 찬 리전이 발견되면 바로 컬렉션을 돌린다.

    ▷ Old 리전의 살아있는 객체는 다른 Old 리전으로 옮겨지며 compaction이 이뤄진다.

    ▷ G1에서 Young, Old 영역 개념은 고정된 개념이 아니다.  

    객체가 새로 할당되는 리전들의 집합이 Young generation 이다.

    프로모션이 일어나는 리전의 집합이 Old Generation 이다.


    G1 GC가 일어나는 단계를 자세히 설명하겠습니다!

     

      G1 GC단계별 사용 방법 (1~5 단계)

      Old Generation의 단계

      G1 Old Generation Collection 단계 (6~10 단계)


    ▷  G1 GC 단계별 사용 방법

     G1 GC에서 힙을 할당하는 방법

     

    1. G1 Heap 구조

    힙은 하나의 메모리 영역이 여러 개의 고정된 크기의 리전으로 분할된 것이다.

    Region크기는 시작 시 JVM이 선택한다.

    JVM은 일반적으로 1~32Mb크기의 다양한 약 2000개 Region을 대상으로 한다.

     

     

    2. G1 Heap할당

    Eden Space, Survivor Space, Old Generation표현으로 매핑되고, Humongous라는영역이 있다.

    영역은 다른 모든 애플리케이션 스레드를 중지하지 않고 병렬로 수집하도록 설계되었다.

    ● Humongous : 지역 크기의 50%를 초과하는 큰 객체를 저장하기 위한 공간

    ● Available / Unused : 아직 사용되지 않은 지역(힙의 미사용 영역)

     

     

    3. Young Generation in G1

    힙은 약 2000개의 영역으로 나뉜다.

    최소 크기는 1Mb

    최대 크기는 32Mb

    파란색은 Old Generation, 녹색은 Young Generation

     

    이전 가비지 컬렉터처럼 영역이 연속적일 필요가 없다.

     

     

     

    4. A Young GC in G1

    살아있는 객체들는 하나 이상의 survivor 영역으로 이동된다.

    aging 임계값이 충족되면 일부 객체는 Old Generation으로 승격된다.

    이것은 Stop the World 이다.

    Eden의 크기와 Survivor크기는 다음 Minor GC를 위해 계산된다.

    이 방식을 사용하면 지역 크기를 매우 쉽게 조정하여 필요에 따라 더 크게 또는 더 작게 만들 수 있다.

     

     

     

     

    5. End of a Young GC with G1

    살아있는 객체들은 survivor지역이나 Old Generation지역으로 이동한다.

    최근 승격된 객체는 진한 녹색으로 표시된다. 


    ▷ Young GC 요약

    ● 힙은 영역으로 분할된 단일 메모리 공간이다.

    ●  Young Generation메모리는 인접하지 않은 영역 집합으로 구성된다. 따라서 필요할 때 크기를 쉽게 조정할 수 있다.

    ●  Minor GC는 Stop the World 이벤트를 한다. 이 작업을 위해 모든 애플리케이션 스레드가 중지된다.

    ●  Minor GC는 여러 스레드를 사용하여 병렬로 수행된다.

    ●  살아있는 객체는 새로운 survivor 또는 Old Generation구역으로 복사된다.


    ▷ Old Generation의 단계

    Phase Description
    (1) initial Mark Old 지역에 객체들이 참조하는 Survival 지역을 찾는다.(STW)
    (2) Root Region Scan 위에서 찾은 Servival 객체들에 대한 스캔 작업 실시
    (3) Concurrent Mark 전체 Heap의 scan을 실시하고, GC 대상 객체가 발견되지 않은 Region은 이 후 단계를  제외한다.
    (4) Remark 애플리케이션을 멈추고(STW) 최종적으로 GC 대상에서 제외할 객체 식별
    (5) Clean up 애플리케이션을 멈추고(STW) 살아 있는 객체가 가장 적은 지역에 대한 미사용 객체를 제거
    (*) Copy GC대상의 Region 이었지만, 완전히 비워지지 않은 지역의 살아남은 객체들을 새로운 지역에 복사하여 Compaction을 수행

     

    Old Generation단계를 자세히 풀면 아래와 같습니다.

     

    ▷ G1 Old Generation Collection 단계

     

    6. Initial Marking Phase

     

     

    7. Concurrent Marking Phase

    비어 있는 영역이 발견되면('X'로 표시) Remark phase단계에서 즉시 제거된다.

    accounting정보도 계산된다.

     

     

    8. Remark Phase

    비어있는 구역은 제거되었다가 다시 채워진다.

    Region liveness는 모든 지역에 대해 계산된다.

     

     

     

    9. Copying/Cleanup Phase

    G1은 liveness가 가장 낮은 지역, 즉 가장 빠르게 수집할 수 있는 지역을 선택한다.

    그런 다음 해당 영역은 Young GC와 동시에 수집된다.

    따라서 Young과 Old Generation이 동시에 수집된다.

     

     

     

    10. After Copying/Cleanup Phase

    선택한 영역이 수집되어 다이어그램에 표시된 진한 파란색 영역과 진한 녹색 영역으로 압축된다.


    ▷ 요약

    ● Concurrent Marking Phase (동시 마킹 단계)

    Liveness 정보는 애플리케이션이 실행되는 동안 동시에 계산된다.

    Liveness정보를 통해 이동, 일시 중지 중에 어느 지역을 회수하는 것이 가장 좋은지 파악할 수 있다.

    CMS와 같은 스위핑 단계는 없다.

     

    ● Remark Phase

    CMS에서 사용했던 것보다 훨씬 빠른 SATB(Snapshop at the Beginning)알고리즘 사용.

    완전히 비어있는 영역이 회수됨.

     

    ● Copying/Cleanup Phase

    Young, Old Generation가 동시에 재생된다.

    Old Generation은 liveness를 기준으로 선택된다.

     

    ZGC

    Z Garbage Collector 

    - Low Latency (저지연)

     

    ZGC는 JDK 11에 실험적 기능으로 추가되었고, JDK 15에서 정식으로 garbage collector로 인정된 다음 LTS(long term support) 버전인 JDK 17에도 반영되었다.

     

    ZGC는 이전 구현과 완전히 다른 방식으로 작동한다.

    '한 세대'로만 작동하는 컬렉터로, Young Generation, Old Generation의 구분이 없다.

    G1 GC와 마찬가지로 ZPage라고 하는 Region이라는 개념이 있으며, 유형별로 구분하지 않고 small(2M), medium(32M), large(N*2MB) 등 크기에 따라 구분한다.

     

    ZGC는 시스템의 스레드와 동시에 실행되므로 가비지 컬렉터가 애플리케이션의 응답 시간에 미치는 영향이 적다(지연 시간이 짧다)

     

    놀라운 점!

    스레드를 동기적으로 관리할 수 있다! (자바 17에 포함된 기능)

    ZGC는 사용하지 않는 메모리를 운영체제로 반환할 수 있어 컴퓨터의 메모리 소비가 우려되는 시스템에서 매우 유용하다.

    메모리는 구성된 최소 힙 크기 이하로 줄어들지 않는 다는 점을 유의하자.

     

    ZGC는 heap이 클수록 더 잘 작동하지만 불필요한 메모리를 낭비하는 것도 비효율적이므로 메모리 사용량과 가비지 컬렉터에 사용할 수 있는 리소스 간의 균형을 조정해야 한다.

     

     

     

    ZPage의 3가지 타입

    Page Type Page Size Object Size Limit Object Alignment
    Small 2M <= 265K <MinObjAlignmentInBytes>
    Medium 32M <= 4M 4K
    Large X * M  > 4M 2M

    각 타입별로 들어갈 수 있는 객체(Object)의 크기가 제한된다.

     

    ZGC메모리 구조

     

     ZPage

    이전 세대의 Garbage Collector인 G1 GC에서는 메모리를 Region이라는 논리적인 단위로 구분한다.

    새로운 세대의 Garbage Collector인 ZGC에서는 메모리를 ZPage라는 논리적인 단위로 구분한다.

    출처 :&nbsp;https://hub.packtpub.com/getting-started-with-z-garbage-collectorzgc-in-java-11-tutorial/

     

    ZPage를 사용할 때 주의할 점은 large타입의 ZPage에는 단 하나의 객체만 할당할 수 있다는 것이다.

    그렇기 때문에 5MB크기의 객체를 large타입의 ZPage에 할당하면 large타입 ZPage의 크기가 medium타입 ZPage의 크기보다 작을 수 있다.

     

    ▷ Colored Pointer

    기본적으로 Linux는 x86-64 아키텍처에서 가상 메모리 주소를 위해 48bit를 사용해 256TB 대역의 가상 메모리를 사용한다. 하지만 ZGC는 가상 메모리 주소를 위해 기본보다 6bit 적은 42bit를 사용한다. 대신 42~45번째 비트의 공간을 colored pointer로 사용해 GC 처리 시 활용한다.

    //  +-------------------+-+----+-----------------------------------------------+
    //  |00000000 00000000 0|0|1111|11 11111111 11111111 11111111 11111111 11111111|
    //  +-------------------+-+----+-----------------------------------------------+
    //  |                   | |    |
    //  |                   | |    * 41-0 Object Offset (42-bits, 4TB address space)
    //  |                   | |
    //  |                   | * 45-42 Metadata Bits (4-bits)  0001 = Marked0      (Address view 4-8TB)
    //  |                   |                                 0010 = Marked1      (Address view 8-12TB)
    //  |                   |                                 0100 = Remapped     (Address view 16-20TB)
    //  |                   |                                 1000 = Finalizable  (Address view N/A)
    //  |                   |
    //  |                   * 46-46 Unused (1-bit, always zero)
    //  |
    //  * 63-47 Fixed (17-bits, always zero)

     

    colored pointer에는 

    - marked0

    - marked1

    - remapped

    - finalizable

    이 있다.

     

    이 중 marked0, marked1, remapped는 각 포인터를 사용하는 GC단계에서 마스킹을 통해 가상 메모리 주소를 가져오는데 사용된다.

     

    가상 메모리 주소를 위해 42bit를 사용하는 ZGC는 4TB~20TB대역의 가상 메모리를 사용하는데, GC단계마다 colored bit에 따라 사용하는 가상 메모리 주소 공간이 달라진다.

    // Address Space & Pointer Layout
    // ------------------------------
    //
    //  +--------------------------------+ 0x00007FFFFFFFFFFF (127TB)
    //  .                                .
    //  .                                .
    //  .                                .
    //  +--------------------------------+ 0x0000140000000000 (20TB)
    //  |         Remapped View          |
    //  +--------------------------------+ 0x0000100000000000 (16TB)
    //  |     (Reserved, but unused)     |
    //  +--------------------------------+ 0x00000c0000000000 (12TB)
    //  |         Marked1 View           |
    //  +--------------------------------+ 0x0000080000000000 (8TB)
    //  |         Marked0 View           |
    //  +--------------------------------+ 0x0000040000000000 (4TB)
    //  .                                .
    //  +--------------------------------+ 0x0000000000000000

     

     

     

     

     

    참고

    https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html

    https://docs.oracle.com/en/java/javase/17/gctuning/introduction-garbage-collection-tuning.html

    https://johngrib.github.io/wiki/jvm-memory/#문서를-읽자

    https://steady-coding.tistory.com/584

    https://golf-dev.tistory.com/52

    https://golf-dev.tistory.com/68

    https://cjw-awdsd.tistory.com/27

    https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

    https://rebelsky.cs.grinnell.edu/Courses/CS302/99S/Presentations/GC/

    https://www.startertutorials.com/corejava/garbage-collection.html

    https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

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

    https://memostack.tistory.com/229#article-3--gc-%EC%A2%85%EB%A5%98

     

    zgc

    https://medium.com/luizalabs/java-garbage-collector-porque-precisamos-conhec%C3%AA-lo-9d26ebb0a6d8
    https://d2.naver.com/helloworld/0128759

    https://hub.packtpub.com/getting-started-with-z-garbage-collectorzgc-in-java-11-tutorial/

     

     

    728x90

    'Programming > Java' 카테고리의 다른 글

    [Java] OOME, JVM8 메모리  (0) 2024.02.29
    [Java] Spring 빌드 Jar, War  (0) 2024.02.29
    [Java] String 클래스  (1) 2024.02.06
    [Java] Java, JVM 개념 정리  (0) 2023.04.27
    [Spring Boot] Visual Studio Code - Spring boot 세팅  (0) 2023.03.03

    댓글

© 2022. code-space ALL RIGHTS RESERVED.