[Java] Garbage Collection

TPark·2020년 5월 27일
0

JVM에서 Garbage Collection은 크게 두가지로 나뉜다. 젊은 세대를 대상으로 한 GC (Minor GC), 그리고 오래된 세대를 대상으로 한 GC (Major GC).

Young generation은 Eden, Survivor1, Survivor2 라는 세가지 영역으로 나뉜다. 새로운 객체는 Eden에 생성되고, Eden이 가득차서 더 이상 새로운 객체를 만들지 못할때 Minor GC가 트리거된다. Eden에서 살아남은 객체는 Survivor1으로 이동하고 Survivor1에서 살아남은 객체는 Survivor2로... 그리고 또 오랜시간 동안 Survivor2에서 살아남은 객체는 Old generation으로 이동한다. Old generation에 대한 Major GC는 기본적으로 메모리가 가득찰때 일어난다.

GC를 수행하는 다양한 알고리즘이 있는데 안드로이드에서는 그중에서도 CMS GC를 사용한다.

기본적으로 JVM은 Parallel GC를 사용하는데, Mark Sweep Compact 단계를 거치는 알고리즘을 사용한다.

Mark 단계에서 메모리를 해제해야할 객체를 판단하고, Sweep 단계에서 지우고, Compact 단계에서 살아있는 객체를 한쪽으로 모은다. Serial GC는 이 작업을 단일 스레드로 수행하고, Parallel GC는 여러개의 스레드로 병렬적으로 수행하기 때문에 훨씬 빠르다. Serial GC는 단일 CPU로 돌아가는 데스크탑을 대상으로 만든 GC이기 때문에 실제 운용서버에서 사용은 적합하지 않다.

CMS GC는 위에서 언급한 Mark Sweep 방식에서 compact 단계를 없애고 Concurrent 단계를 추가한 방식이다. 초기의 init단계에서 가장 가까운 살아있는 객체를 찾고, Concurrent mark 단계에서 방금 살아있다고 판단한 객체가 참조하는 값을 찾는다.

그 다음 remark 단계에서 Concurrent mark 단계에서 새로 추가되거나 끊긴 객체가 있는지 확인 후, Concurrent sweep 단계에서 쓰레기를 처리하는 작업을 한다. Concurrent 단계의 특징은 다른 스레드가 실행중인 동시에 진행된다는 점이다. 때문에, stop the world가 일어나지 않는다.

CMS 방식은 stop the world 시간이 매우 짧은 대신에, 메모리와 CPU를 더 많이 사용하고 compaction 단계가 제공되지 않는다는 단점이 있다.

그리고 Compaction 작업을 수행할 시에, 조각난 메모리가 많아서 stop the world 시간이 다른 GC보다 길어지기 때문에 잘 확인하고 사용해야 한다.

0개의 댓글