Java (자바)

[Java] Garbage Collector

Oscar:) 2024. 3. 6. 18:21

 

 

이번 포스팅에서는 Garbage Collector에 대해 알아보자.

 

 

 


 

 

Garbage Collector

 

 

직역하면  ' 쓰레기 수집가 '

 

 

Java의 메모리 관리 기법 중 하나이다.

 

프로그램이 할당했던 메모리 중에서

더 이상 사용되지 않는 메모리를 해제하는 기능이다.

 

더이상 사용되지 않는 메모리를 해제해주지 않으면

메모리가 계속 쌓이기만 하는 메모리 누수가 발생한다.

 

 

 

C언어의 경우, 더 이상 사용되지 않는 메모리는 직접 해제해준다.

 

하지만 Java의 경우 개발자가 메모리를 직접 해제해주는 일이 없다.

 

그 이유가 바로 Garbage Collector의 존재 덕분이다.

 

 

 


 

Heap 영역 /  Minor GC · Major GC

 

 

✅ Garbage Collector는 JVM의 Heap 영역에서 동작한다.

 

 

Heap 영역이 뭐에요?

 

[Java] JVM 메모리 할당 방식 - Stack · Heap Memory

지난 포스팅에서 JDK · JRE · JVM에 대해 간단히 알아보았다. [Java] JDK · JRE · JVM JDK · JRE · JVM에 대해 알아보자. JDK Java Development Kit Java로 프로그램을 개발하는데 필요한 툴을 모아놓은 소프트웨어

oscarstory.tistory.com

 


 

 

 

JVM의 Heap 영역은 애초에 다음 2가지를 전제로 설계되었다.

 

● 대부분의 객체는 일회성이다.

● 대부분의 객체가 메모리에 오랫동안 남아있는 경우는 드물다.

 

 

 

 

따라서 Heap 영역은 Young · Old 2가지로 분류되었다.

 

Heap 영역 구조

 

 

● Young Generation : 새로 생성된 객체가 할당되는 영역

 

- 위에서 언급했지만, 대부분의 객체가 이곳에 생성되었다가 사라진다.

 

- Young 영역에서 일하는 Garbage Collector를 Minor GC라고 부른다.

 

- Young 영역은 다시 Eden · Survivor 영역으로 나뉜다.

 

*Eden : 생성된 직후의(따끈따끈한) 데이터가 저장되는 곳

*Survivor : Eden에서 해제되지 않고 비교적 길게 살아남은 데이터가 저장되는 곳

 

 

※ Heap 영역부터 시작해서, Young 영역을 세분화하는 이유에 대해서는

아래 Garbage Collector 동작 방식에서 다뤄보겠다.

 

 

 

 

● Old Generation  : 드물지만 Young 영역에서 오랫동안 남아있는 객체가 복사되는 영역

 

- Old 영역으로 옮겨진 객체는 이후로도 오래 남아있을 가능성이 높기에 Young 영역보다 크게 할당된다.

 

- Old 영역에서 일하는 Garbage Collector는 Major GC라고 부른다.

 

 

 

 

요약

 

● 객체가 생성되면 대부분 Heap 영역 내 Young 영역 내 Eden 영역에 할당된다.

 

● 객체가 생존 기간에 따라 Eden(Young) → Survivor(Young) → Old 영역으로 이동된다.

 

● 대부분의 객체는 Young 영역에서 사라지고, 일부만이 Old 영역까지 이동된다.

 

● Heap 영역에서 객체를 삭제해 주는 것이 Garbage Collector다.

 

 

 


 

Garbage 구분 기준

 

 

쓰레기를 수집한다는 것은 알겠는데,

내가 작성한 소중한 코드 중에.. 어떤 부분이 쓰레기라는 거지...? 

 

 

Garbage Collector는 쓰레기 판단의 확고한 기준을 가지고 있다.

 

→ Reachability (도달 가능성)

 

 

Reachability는 다음 2가지로 나뉜다.

 

● Reachable (도달 가능)

Unreachable (도달 불가능)

 

 

직역하면 도달 가능성에 대한 이야기지만,

해당 객체에 대한 유효한 참조 여부를 판단한다고 생각하면 된다.

 

 

말이 어려우니 그림으로 보자.

 

출처 : NAVER D2 - GC와 Reachability

 

 

Thread, Method Area에 대한 추가적인 설명을 붙이기엔 너무 복잡해지기에,

이번 포스팅에서는 단순히 Heap 영역의 객체를 참조하는 영역이라고만 생각하고 보자.

 

 

Heap 영역 내 화살표로 이어진 객체들이 참조가 유효한 것이므로 Reachable 상태다.

반대로 참조가 없이 홀로 떠다디는 객체가 Unreachable 상태다.

 

 

Garbage Collector의 수집 대상은 Unreachable 상태인 객체들이다.

 

 

 


 

Garbage Collector 동작 방식

 

 

Garbage Collector가 뭐하는 친구인지,

어떤 Garbage를 수집하는지 알아보았으니

 

어떻게 동작하는지 간단히 알아보자.

 

 

대표적인 2가지 방식을 설명할 수 있다.

 

● Stop The World

● Mark and Sweep

 

 

 

✅ Stop The World

 

 

Garbage Collector가 실행될 때는

JVM이 GC를 제외한 모든 스레드를 정지시킨다. 

 

GC가 일을 마치면 다시 기존의 스레드가 재개된다.

 

이는 사용자 입장에서 프로그램이 정지되는 듯한 느낌을 준다.

(화면이 버벅거리는 등)

 

 

...그러면 안 되는 것 아닌가 ?

 

당연히 버벅거림은 최소화해야 한다.

 

 

 

이를 해결하기 위한 노력 중 하나로,

Heap 영역의 세분화를 이야기할 수 있다.

 

 

 

위에서도 한 번 설명했지만, 다시 생각해보자.

Heap 영역을 Young · Old 영역으로 쪼개고,
Young 영역을 다시 Eden · Survivor 영역으로 쪼갠다.
심지어 Survivor 영역은 Survivor1 · Survivor2 영역으로 나뉘어 있다.

 

 

 

결론적으로, 객체가 오래 살아남는다는 가정하에 다음과 같이 이동한다.

Eden → Survivor1 → Survivor2 → Old

 

 

객체가 영역을 이동한다고 표현했지만, 사실 GC가 작동하는 것이다.

 

Eden에서 Survivor1로 객체를 복사하고, Eden의 객체는 삭제(쓰레기 수집)되는 원리다.

이를 Stop And Copy 알고리즘이라 부른다.

 

 

 

이렇게 GC의 빈도 수를 늘려서, 한 번의 긴 정지 시간이 아닌

매우 짧은 정지 시간을 여러번 반복하는 방향을 선택한 것이다.

 

결국 Stop The World의 최대 실행 시간을 최소화하려는 노력이며

그렇기에 사용자는 GC로 인한 프로그램의 정지를 웬만해서는 느끼지 못한다.

 

 

 

하지만 Heap 영역의 세분화로도 처리가 힘들 때는 별도의 작업을 하기도 한다.

이를 'GC를 튜닝한다' 라고 표현한다.

 

 

 


 

✅ Mark and Sweep

 

 

● Mark : 유효한 참조가 있는 객체와 그렇지 않은 객체를 식별하는 작업

● Sweep : 그렇지 않은 객체를 수거하는 작업

 

 

Stop The World를 통해 온전히 GC만의 시간이 펼쳐지는 동안,

Heap 메모리의 객체를 Reachability를 기준으로 탐색 · 삭제하는 과정을 말한다.

 

*Reachability : 위에서 설명했지만, 객체의 참조 여부를 뜻한다.

 

 

 

 

 


 

 

 

 

 

이번 포스팅에서는 Garbage Collector에 대해 알아보았다.

 

언젠가 Garbage Collector를 신경써가며 작업할 날이 오지 않을까 생각한다.