[Android]가비지 컬렉터(Garbage collector)

2022. 4. 11. 00:45Tech/Mobile(Android, iOS)

    목차

이 글은 이전에 운영하던 깃 블로그에서 옮겨온 글입니다.

 

서론

C/C++을 주로 쓰던 시절, 메모리 관리를 수동으로 해주어야 했습니다. 할당을 해주면, 사용이 끝난 후 적절한 시점에 해제를 해주어야 했죠. Native 언어다 보니 개발자가 관여하는 부분이 많았습니다. 이에 반해, C# 같은 Managed 언어를 사용하면서 메모리 관리 방식이 바뀌게 되었습니다. 정확히는 신경 쓰는 방식이 바뀌었다는 게 맞겠네요.

C#, Java 같은 Managed 언어는 메모리를 자동으로 관리해 줍니다. 바로 가비지 컬렉터를 통해서 말이죠. 본래 저는 Unity를 주력으로 사용하여 C#이 메인 언어이지만, C#의 가비지 컬렉터에 관해서 글을 쓰기 전에 Java/Android의 가비지 컬렉터에 대해 먼저 살펴보려 합니다.


가비지(Garbage)

 

 가비지 컬렉터는, 가비지(Garbage)라는 것을 수집하는 녀석(Collector)이라는 것인데, 그럼 우선 가비지가 무엇일까요?

직역하면 쓰레기입니다. 더 이상 사용되지도 않고 자리만 차지하는 무용지물을 우리는 쓰레기라고 부릅니다. 메모리 관리 관점에서 보자면, '사용이 끝나 해제되어야 하는 메모리'라고 생각하면 됩니다.


가비지 컬렉터(Garbage collector)

 가비지를 수집하는 행위를 가비지 컬렉션(Garbage collection, GC)이라 부르고, 이를 행하는 녀석을 가비지 컬렉터(Garbage collector)라고 부릅니다. 중점적으로 봐야 하는 것은 가비지 컬렉션(GC)입니다.

 

 가비지 컬렉터가 수집을 하기 전에, 가비지를 어떻게 판단하는지 먼저 살펴보겠습니다. 할당된 메모리 중 수집 대상이 되는 것들은 '참조 루트(Root Set of References)'에 의해 관리됩니다. 참조 루트로부터 연결되기 시작해, 수집 대상인지 여부를 판별하게 됩니다. 그러므로, 참조 루트에 연결되지 않은 메모리는 수집 대상에서 제외된다고 보면 됩니다.

[그림 1. 참조 루트]

참고로, 참조 루트에서부터 탐색되지 않는 노드(객체)들은 메모리에서 제거하기 전에 finalize()를 호출합니다. 위 그림에서 Unrechable Objects들이 그러한 녀석들입니다.

 

참조 루트에 연결된 메모리들은 Heap 영역에 할당된 메모리들입니다. 주로 런타임에 동적으로 할당된 녀석들입니다. JAVA의 가비지 컬렉터(이하 JAVA GC) 또한 JVM의 힙 영역에서 메모리를 관리합니다.

[그림 2. JVM 의 Heap]

위 그림에 나와 있는 것처럼, JVM의 힙 영역을 크게 3 부분으로 나눕니다.

  • Young : 메모리가 처음 할당되고 일정 주기 살아남았을 경우 머무는 영역
    • Eden : 메모리가 가장 먼저 할당될 때 지정되는 곳
    • Survivor : Eden에서 쌓인 메모리가 일정 주기가 지난 후 이동되는 영역 이곳은 Survivor1, 2로 나뉘며 둘 중 한 영역은 반드시 비어있음
  • Old : Young 영역에서 계속 살아남아 Young 영역이 차게 되면 이동하는 영역
  • Permanent : 클래스와 메서드 영역, 언어단에서 사용되지 않음

이렇게 각 영역에 할당된 메모리들이 가비지가 되어 GC의 대상이 되는 경우는 아래와 같습니다.

  • 모든 참조가 해제된 경우(참조 자체가 null 인 경우)
  • 블록({ … }) 안에서 생성되고 사용이 끝난 경우
  • 부모 객체가 null이 되는 경우 해당 객체의 자식은 수집
  • weak 참조만 가지고 있는 경우
  • soft 참조이지만 메모리가 부족한 경우 (Java에서 제공하는 soft reference 클래스로 만든 객체)

참고로 위 경우는 C#에서의 0세대, 1세대, 2세대와 다르지 않습니다. 자세한 내용은 C#의 가비지 컬렉터 때 다뤄 보겠습니다.


GC 종류

위에서 설명한 영역에서 발생하는 GC는 서로 다른 종류입니다.

  • Minor GC : Young 영역에서 발생하는 GC. 가장 빈번하게 발생
  • Major GC : Old 영역에서 발생하는 GC.
    Young 영역에서 살아남고, 크기가 큰 객체들이 위치하는 만큼 빈번하지는 않습니다(Full GC라고도 불림)

GC 방식

Serial Collector(시리얼 컬렉터)

싱글 스레드 머신에서 사용되는 기본 GC방식입니다. Young 영역과 Old 영역이 연속적으로(시리얼)하게 진행되며, 이때 애플리케이션의 수행은 중지되고 Young -> Old 영역으로 이동한 객체들은 Mark-sweep-compact 알고리즘을 따라 수집됩니다. 그럼 Mark-sweep-compact 알고리즘은 무엇일까요? 간단한 설명은 아래에 있습니다.

 

Mark-sweep-compact 알고리즘을
a. Old 영역에서 살아있는 객체를 식별(Mark)
b. 식별한 Old 영역 객체들 중 수집될 가비지 판별(sweep)
c. 가비지는 지우고, 살아남을 객체들은 분리(compact)

주로 대기시간이 길어도 상관없는 작업에 많이 이용된다고 합니다. 참고로 애플리케이션의 수행이 중지되는 시점을 Stop the world라고 부른다고 하네요.

 

Parallel Collector(병렬 컬렉터)

multi-CPU 유닉스 머신이나, 64-bit JVM 머신에 사용되는 기본 컬렉터입니다. Throughput Collector라고도 부릅니다. 시리얼 컬렉터와 달리 Young 영역에서 가비지 컬렉션이 병렬적으로 일어나며 Old 영역에서는 시리얼 컬렉터와 마찬가지로 Mark-sweep-compact 알고리즘을 따릅니다.

[그림 3. 병렬 컬렉터의 병렬 처리]

병렬로 처리되는 덕분에 시리얼 콜렉터 보다 애플리케이션의 수행 정지가 적다고 합니다. Old 영역에서 Mark-Summary-Compact 알고리즘을 따를 경우 Parallel Old GC라고 부른며, sweep과 summary의 차이는 sweep은 단일 스레드가 객체들을 훑었다면(가비지 판별) summary는 여러 스레드가 Old 영역을 나누어 훑는 것입니다. 또한 효율을 위해 앞선 GC에서 Compaction 된 영역을 별도로 훑습니다.

 

CMS Collector

low-latency collector라고도 불리며, 시리얼/병렬 컬렉터에서 Long pause(수행 중지가 오래 진행) 되는 걸 막기 위해 디자인되었다고 합니다. Young 영역에서는 병렬 컬렉터와 같지만 Old 영역에서 차이가 있습니다. Stop the world가 발생한 이후 다음과 같이 진행됩니다.

  1. Initial marking : 살아있는 객체 판별
  2. Concurrent Mark : 참조를 따라가면서 표시
  3. Remark : Concurrent mark 단계에서 새로 추가되거나 끊긴 객체를 재판 별
  4. Concurrent Sweep : 수집된 가비지를 정리한다 별도의 Compaction(구분)이 없음

위에서 보듯이 별도의 Compaction 이 없고, CPU 사용량이 많아 이 때문에 메모리 단편화가 많을 수 있어 오히려 Stop the world의 시간이 더 늘어날 수 있습니다.

 

G1 Collector(Garbege First 컬렉터)

JAVA 7에서 새롭게 소개된 GC. 4GB가 넘는 큰 힙을 처리하기 위해 디자인된 컬렉터입니다. 동일하게 Stop the world를 최소화하며, 힙을 여러 영역으로 나누어 GC를 진행합니다. 이전의 GC들은 Young 영역과 Old 영역을 같습니다. 하지만 G1의 경우에는 아 래와 같이 영역이 각각 Eden, Survivor, Old영역의 역할을 동적으로 바꿔가며 GC가 일어납니다.
Young 영역의 GC와 Old 영역의 GC는 모두 CMS콜렉터 방식과 유사합니다.

[그림 4. G1 에서 역할을 동적으로 바꾸는 경우]

 


리소스 출처

 

[그림 1] : 금광캐는광부 tistory, https://itmining.tistory.com/24

[그림 2,3 ] : 12bme tistory, https://12bme.tistory.com/57

[그림 4] : Preamtree의 행복로그, https://preamtree.tistory.com/118

반응형
LIST