Garbage Collection

이재연·2021년 4월 27일

Garbage Collection이란?

프로그램은 실행 할 때 필요한 메모리를 할당 받는다. 메모리는 한정적이기 때문에 관리가 필요하다. 이때 사용하지 않는 메모리를 회수하는 과정을 GC(Garbage Collection) 이라고 한다.

GC를 처리할 때 모든 스레드가 작업을 정지하는 순간이 발생한다. 이를 stop-the-world라고 한다.

많은 언어은 GC를 포함하고 있고 자바 역시 GC를 제공한다.

Java에서의 GC

자바에서 GC는 JVM이 수행한다. JVM은 Heap Memory 영역에서 사용하지 않는 메모리를 찾아서 회수한다. 그렇다면 사용하지 않는 메모리 라는걸 어떻게 판단할까?

JVM Space

먼저 JVM의 구조에 대해 간단히 알아보자.
JVM은 크게 Class Loader, Execution Engine, Runtime Data Area로 구성되어 있고, Runtime Data Area는 다시 PC Register, Stack, Native Method Stack, Heap, Method Area로 이루어져 있다.

Runtime Data Area는 JVM이 운영체제로 부터 할당받은 메모리 영역이다. Heap 영역을 기준으로 Threads, Method 같은 외부 영역을 Root Set이라고 한다.

Reachable

Root Set에서 직접 참조하거나 참조 사슬에 속한 객체들을 Reachable Object라고 하며, 그렇지 않은 객체는 Unreachable Object라고 한다.

이때 Unreachable Object가 GC의 대상이다.

GC 동작 과정

Heap Space

Java HotSpot VM을 기준으로 Heap 영역은 크게 Young GenerationOld Generation으로 나뉜다. GC는 Young 영역과 Old 영역에서 각각 수행된다.

Young 영역에서 발생하는 GC를 Minor GC, Old 영역에서 발생하는 GC를 Major GC라고 부른다.

Minor GC

Minor GC

객체는 생성되면 먼저 Eden영역에 할당된다.

Eden 영역이 가득차면 Minor GC가 일어나고, 살아남은 객체는 Survivor 영역으로 이동한다.
하나의 Survivor 영역이 가득 차면 다시 GC가 일어나고, 여기서도 살아남은 객체는 다른 Survivor 영역으로 이동한다. 이때 원래 Survivor 영역은 비워진다.
옮겨진 Survivor 영역에서도 살아남는다면 Tenured 영역으로 이동한다.

Major GC

Old 영역에서의 GC는 Tenured 영역이 가득차면 일어난다. GC에 따라 방식이 달라지지만 크게 두가지 과정을 수행한다.

검사(Marking) : 사용하지 않는 객체를 찾는다. 주로 이 과정에서 stop-the-world가 발생한다.
사용하지 않는 객체 제거 : 메모리를 회수하고 압축한다.

GC의 종류

  • Serial GC
    단일 스레드로 GC를 실행한다. 검사와 제거를 수행한다.

  • Parallel GC
    여러개의 스레드를 사용하여 GC를 수행한다. JDK 8까지의 기본 GC이다.

  • CMS(Concurrent Mark Sweep) GC
    Root Set에서 맨처음 참조되는 객체만 찾고 초기 검사를 끝낸다. 이후 애플리케이션이 동작하는 환경에서 참조 사슬을 따라 검사를 진행한다. 그래서 다른 GC에 비해 stop-the-world 시간이 짧다. 하지만 도중에 참조가 바뀔수도 있고, 애플리케이션과 동시에 GC를 수행하기 때문에 리소스 사용량이 크다. JDK 9부터는 사용하지 않는다.

  • G1(Garbage First) GC
    CMS와 같은 방식으로 수행한다. 차이점은 Young영역과 Old영역을 비 연속적인 바둑판 형식으로 관리한다. 그래서 모든 Old 영역이 가득차지 않아도 Old 공간을 확보할 수 있다. JDK 6 부터 추가되었고 JDK 9 부터는 기본 GC로 설정된다.

  • Z GC
    비연속적이고 크기도 다른 구조를 사용하며, Colored PointerLoad Barriers라는 개념이 도입되었다. 64bit 체제에서만 사용 가능하다. bit에 각 메모리에 객체의 상태를 저장하는 Colored Pointer를 두고 상태와 재배치 여부 등을 저장한다. Colored Pointer를 통해 회수하거나 재배치할 메모리를 빠르게 찾는다. 또한 64 bit 구조이기 때문에 대용량 힙 구조에 적합하다. JDK 11부터 추가되었다.

GC Heap Use

G1 GC는 Heap을 동일한 단위의 크기로 나눠서 사용한다. 어떤 영역은 Young 영역이 될 수 있고 어떤 영역은 Old 영역이 될 수 있다.
Z GC는 Z Page라는 크기로 나눠서 사용한다. 2MB 단위로 동적으로 생성한다.

참조

https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
https://docs.oracle.com/en/java/javase/11/gctuning/index.html
https://plumbr.io/handbook/what-is-garbage-collection
https://dzone.com/articles/minor-gc-vs-major-gc-vs-full
https://d2.naver.com/helloworld/1329
https://d2.naver.com/helloworld/329631

0개의 댓글