본문 바로가기

Java/JVM

[JVM] Heap & GC

이번 장에서는 Oracle 공식문서와 여러 블로그들의 글을 정리하면서 Java Heap에 대해서 알아보도록 한다.


먼저 많은 블로그들에 있는 Heap 구조를 살펴보면 아래와 같다.

그림1: Java8 이전의 메모리 구조
(출처: https://asfirstalways.tistory.com/158)

그림에서 Permanent영역은 java8부터는 제거되었으며 Class나 Method의 메타 정보들이 Native Memory의 Metaspace영역으로 이동하였다.
Native Memory는 Heap 영역의 바깥인 Off-Heap 공간을 의미하며 시스템의 기본 메모리라고 생각하면 된다. Java 어플리케이션은 크게 Heap영영과 Off-Heap 두 공간을 활용하여 동작한다. Off-Heap영역도 Java 어플리케이션이 사용하는 메모리 영역이므로 어플리케이션을 구동할 때 사용할 메모리의 총 량을 계산할 때 염두해두어야한다. Heap 영역은 JVM에 의해 관리된 영역이며 Native Memory는 OS레벨에서 관리하는 영역으로 이해하면 좋을 듯 하다.

그림2: Java8 이후의 Heap 구조
(출처: https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/generations.html)

그림3: Java8 이후의 Heap & OffHeap 구조
(출처: https://www.samsungsds.com/kr/insights/1232761%5C_4627.html)

그림을 살펴보면 Java7까지는 존재하였던 Permanent 영역이 사라지고 Native Area에 Metaspace가 생성된 것을 확인할 수 있다.
단, 기존에 Permanent영역에 존재하던 Static Object는 Heap 영역으로 이동하여 Java8 이후에도 GC의 대상이 된다.
작성일 기준으로 많으 프로젝트들이 Java8 이상의 버전으로 작성되어 있으므로 그림2를 기준으로 살펴보도록 한다.

Heap영역은 크게 New/Young Generation과 Old/Tenured Generation 영역으로 구분된다.

  1. Minor GC
    메모리에 객체가 생성되면 Eden영역에 객체가 할당(Allocation)된다.
    Eden영역이 가득차면 Eden영역에 있던 객체가 Survivor1 또는 Survivor2로 옮겨진다.
    이렇게 Eden영역이 비워지고 Survivor 영역으로 객체가 이동하는 동작을 Minor GC(1차 GC)라고 한다.
  2. Major GC
    모든 객체는 Age bit를 가지고 있으며 Minor GC가 발생할 때마다 증가하도록 되어있다.
    Age bit가 일정 수치(Max Tenuring Threshold)를 초과하게 되는 경우 Old/Tenured Generation 영역으로 객체가 이동(Promotion)하게 된다.
    Old/Tenured Generation 영역이 가득차게되면 Major GC(2차 GC)가 발생한다.
    Major GC의 경우 모든 GC를 진행하는 Thread를 제외한 모든 Thread의 동작이 멈추는데 이러한 상태를 Stop-the-world라고 한다.
    현재까지 발표된 모든 GC알고리즘 중 어떤 알고리즘을 사용하더라도 Stop-the-world를 피할 수는 없으며 개발자들이 GC를 튜닝하는 가장 큰 목적이 Stop-the-world 시간을 최소화하기 위함이다.

지금까지 간략하게 Java Heap과 GC에 대해서 알아보았다.
다음 장부터는 GC별 작동원리에 대해서 알아보도록 한다.

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

[JVM] GC 벤치마크 결과  (0) 2022.01.23
[JVM] GC 벤치마크 분석 포인트  (0) 2022.01.23
[JVM] GC 벤치마크 개요  (0) 2021.12.23
[JVM] GC 알고리즘 종류  (0) 2021.12.02
[JVM] JVM 이란?  (0) 2021.12.02