Garbage Collection 알아보기

박진형·2022년 5월 24일
0

JAVA

목록 보기
3/3
post-thumbnail

Garbage Collection이란?

Garbage Collection이란, 시스템에서 더 이상 사용되지 않는 메모리를 Garbage Collector가 회수하여 다시 사용할 수 있는 자원으로 만들어 주는 기능이다. 줄여서 GC라는 용어로 많이 쓰인다.

Garbage Collection이 필요한 이유?

애플리케이션 동작중 발생하는 사용하지 않는 메모리는 회수 되어야한다. 이러한 회수가 이루어지지 않고 메모리가 점유되어 낭비가 되고 있는 상황을 메모리 릭(Memory leaks)이라고 한다.

c나 c++ 언어에서는 메모리를 자동으로 회수해주는 GC가 없다. 그러므로, 개발자가 직접 사용하지 않는 메모리를 회수하는 코드를 작성을 해야하는데, 이 작업이 만만치않다. 회수를 누락할 수도 있고, 회수를 했던 메모리를 다시 사용하려고 할 수도 있고 다양한 버그들이 발생하기 쉽상이다.

개발자는 핵심 비즈니스 로직을 개발하기도 바쁜데, 이러한 메모리 관리 부분도 신경을 써줘야한다니..
그래서 JAVA의 JVM은 메모리 관리를 대신 해주며, 개발자는 메모리 관리 부분에 대한 신경을 덜고 애플리케이션을 개발할 수 있도록 해준다.

GC의 메모리 수거 방법

자바에서 메모리 수거의 대상을 구별할 때에 Reachable한지, Unreachable한지 체크를 하고 Unreachable하다면 메모리를 수거하는 방식으로 동작한다.

Reference Counting

힙 영역에 생성된 객체들에게 각각 참조되는 횟수를 체크하는 reference count가 관리 되는데, 객체를 접할 수 있는 방법의 수를 뜻한다. reference count가 0이라면 GC의 대상이 되는 것이다.

Reference Counting의 문제점 - 순환 참조

A에서 B로 향하는 참조가 끊기면 {B, C, D, E}는 GC의 대상이 되어야 하지만, 참조 카운트가 0이 아니기 때문에 GC의 대상이 되지 않는다. 이러한 문제 때문에 메모리 누수가 발생한다.

Mark and Sweep, Compact

기본적으로 Mark and Sweep, Compact 과정을 수행한다. Compact 과정은 필수는 아니라고 한다.
GC에는 GC Root라는 것이 존재하는데 힙 외부에서 접근할 수 있는 변수나 오브젝트를 뜻한다.
이 GC Root로부터 시작해 참조가 되는 오브젝트들을 탐색하는데 이 과정을 Mark 라고 한다.

Mark가 완료되면 Mark되지 않은 메모리들을 해제한다. 이 과정을 Sweep 이라고 한다.

그리고 단편화를 줄이기 위해 메모리들을 정렬하는 과정을 Compact라고 한다.

GC는 언제 실행될까?

GC가 JVM의 Heap에서 Young Generation에 대해서 발생하면 minor GC, Old Generation에서 발생하면 major GC라고 부른다.

Eden은 새롭게 생성된 객체들이 할당되고 여기서 Sweep되지 않은 객체들이 Survivor 영역으로 이동된다.
Survivor영역은 0,1로 나뉘는데 Survivor 영역의 특징은 Survivor0, 1 영역 중 한 영역은 꼭 비워져 있어야한다.

이 Eden 영역이 가득차게 되면 minor GC가 발생한다.

Survivor로 이동된 객체들은 age bit가 부여되는데, 특정 임계치에 도달하면 Old 영역으로 이동된다.

Old영역이 가득차게 되면 major GC가 발생한다.

💡 Stop-The-World : GC를 수행하는 동안은 GC를 수행하는 쓰레드 외의 쓰레드들은 모두 작업을 중단하는 현상. GC의 종류에 따라 stop-the-world 시간이 각각 다르다. 실시간성이 아주 중요한 애플리케이션에서는 GC가 발생하면 애플리케이션이 멈추기 때문에 큰 장애로 이어질 수 있다.

GC의 종류

Serial GC

GC를 처리하는 쓰레드가 1개로 다른 GC에 비해 stop-the-world 시간이 길다.
서버 환경과 같은 다중 쓰레드 애플리케이션에서는 부적합하다.

Parallel GC

자바8의 기본 GC이며, Serial GC와는 다르게 힙 영역 관리를 위해 여러 스레드를 사용하지만 GC를 수행하는 동안 다른 모든 쓰레드의 작업이 중단되는것은 마찬가지다. 다만 stop-the-world의 시간이 단축된다.

CMS GC

Garbage의 수집을 위해 다중 쓰레드를 사용한다. stop-the-world 시간을 줄이기 위해 고안되었다.
평균적인 애플리케이션의 성능이 줄지만, Garbage 수집을 하는 동안 쓰레드가 멈추지 않는다.
성능을 위해 많은 CPU를 할당할 수 있다면 Parallel GC보다 더 나은 선택이 될 수 있다.
compact과정이 없어 단편화 문제가 발생한다.
자바 9에서 더이상 사용되지 않으며 자바 14에서는 지원을 완전 중단했다.

G1 GC

자바 9 이상의 기본 GC이며 CMS GC를 개선한 방식이다. 메모리 공간이 큰(4GB 이상) 다중 프로세서 시스템에서 실행되는 응용 프로그램을 위해 설계되었다.

힙을 동일한 크기의 청크(region)로 나누고 우선 순위를 지정해 우선 순위에 따라 해당 청크에서 병렬 가비지 수집을 수행한다.

eden, survior, old이외에도 Humongous region과 Available/Unused region 의 2가지 타입의 region이 추가적으로 존재한다.

  • Humongous region : 객체의 크기가 region 영역의 1/2보다 클 경우 사용된다
  • Available/Unused region : 아직 사용하지 않은 영역

0개의 댓글