Inor

[JAVA] GC(Garbage Collection : 종류와 과정) 본문

Computer Engineering/Java

[JAVA] GC(Garbage Collection : 종류와 과정)

Inor 2017. 7. 13. 14:32

Garbage Collection


 C와 C++을 공부 해봤던 사람이라면 객체나 메모리를 할당 할때 특정 명령어(malloc, new)를 사용하는 것을 알고 있을 것 입니다. 그리고 메모리를 해제하는 명령어(free, delete) 사실을 알고 있을 것 입니다. 그러나 자바에서는 개발자가 객체를 생성하는 것은 가능하지만 메모리에 할당된 객체를 삭제하는 것은 허락하지 않습니다. 자바가 추구하는 것들 중 하나가 메모리 관리의 편리성이기 때문이라고 알고 있습니다.




Stop-The-World

 

 자바는 멀티 스레드 환경이고 Garbage Collection 또한 특정 스레드에서 동작 하게 됩니다. Garbage Collection이 실행 될 때 애플리케이션의 모든 스레드는 정지하고 Garbage Collection 스레드만 동작하게 됩니다. 이것을 Stop-The-World라고 합니다. 개발자가 임의로 Garbage Collection을 호출 할 수 있지만 이런 행동(System.gc())은 애플리케이션의 성능을 떨어뜨리는 행동이 될 수 있습니다. Garbage Collection 튜닝의 기본은 Stop-The-World의 시간을 줄이는 것이라고 합니다.




Young Generation & Old Generation


 Heap 영역은 Garbage Collection의 대상이 되는 영역들 중 하나 입니다. Heap 영역에는 크게 Young Generation과 Old Generation으로 영역이 나뉘어져 있습니다. '대부분의 객체는 금방 접근 불가 상태(unreachable)가 된다.'와 '오래된 객체가 젊은 객체를 참조하는 경우는 드물게 존재한다.'는 두 가지 가설의 장점을 최대한 살리기 위해서 만들어진 영역들 입니다.


  • Young Generation : 새로 생성된 객체들은 이 영역에 속하게 되고 그 객체들 중 대부분은 금방 접근 불가 상태가 되기 때문에  Garbage Collection의 대상이 됩니다. 이 영역에서 객체가 사라질 때 Minor GC가 호출이 됩니다.
  • Old Generation :  Young 영역에 있던 객체들이 참조를 잃지 않고 오래 살아 남으면 Old 영역으로 이동이 됩니다. 대부분 Young 영역보다 크게 할당이 되고 크기가 크기 때문에 자주 GC가 호출이 되지 않습니다. 이때 호출되는 GC를 Major GC라고 부릅니다.

 만약, Old Generation에 있는 객체가 Young Generation의 객체를 참조 한다면 Card Table이라는 곳에 해당 정보를 저장 합니다. 그렇게 되면 Young 영역에대한 GC를 실행할때 Card Table을 확인해서 어떤 객체가 GC의 대상에서 제외 되는지 Old 영역 전체를 확인하는 것 보다 빠르게 확인 할 수 있습니다. 결과적으로 Minor GC의 시간을 줄여주게 됩니다.



Young Generation의 구성과 CG


 Young Generation은 Eden과 두개의 Survivor 영역으로 총 3개의 영역으로 구성 됩니다. Minor GC에대한 설명을 위해서 두개의 Survivor영역을 Survivor0와 Survivor1이라고 칭하겠습니다. 최초의 생성된 객체는 Eden에 자리 잡게 됩니다. 그렇게 생성된 객체들 중 참조를 잃지 않은 객체들은 Survivor0 영역으로 이동하게 되고 Survivor1 영역과 Eden 영역에대한 GC가 실행 됩니다. 그리고 시간이 지나면서 다시 Eden 영역에 새로운 객체들이 생성되고 몇몇 객체들은 다시 참조를 잃게 되는데 Eden과 Survivor0에서 참조를 잃지 않은 객체들은 Survivor1 영역으로 이동하게 되고 Survivor0와 Eden에대한 Minor GC가 발생하게 됩니다. 이런 과정을 반복하면서 살아 남은 객체들은 Old Generation으로 이동하게 됩니다.



Old Generation에서의 GC 방법들

 Old Generation에서는 기본적으로 영역이 가득 차면 GC를 호출 합니다.

  • Serial GC
 Serial GC의 경우에는 Mark-Sweep-Compact라는 알고리즘을 사용합니다. Old 영역의 살아있는 객체들을 식별(Mark)하고 그런 다음에 Heap의 앞 부분부터 확인하여 살아 있는 객체들만을 남기도록 합니다.(Sweep) 마지막으로 힙의 앞 부분부터 채워서 객체가 존재하는 부분과 객체가 없는 부분으로 나눕니다. 이 방식은 하나의 코어가 있을때 사용하도록 만들어진 것이기 때문에 적은 CPU 코어의 갯수에서 사용해야 합니다.

  • Parallel GC
 Parallel GC가 동작하는 방식은 Serial GC와 동일한 방식으로 동작 합니다. 그러나 하나의 스레드에서만 처리하는 Serial 방식과는 다르게 Parallel 방식은 여러개의 스레드가 동시에 처리 하는 방식을 사용 합니다.


  • Old Parallel GC
 Young Generation에서는 Parallel GC와 같은 방식으로 작동 하지만 Old 영역에서는 다른 방식으로 작동 합니다. Mark-Summary-Compact 알고리즘을 사용하고 기존의 Sweep 대신에 있는 Summary 단계에서는 앞서 GC를 수행한 영역에대해서 별도로 살아있는 객체를 식별한다는 점에서 다르고 더 복잡한 방식을 사용 합니다.

  • Concurrent Mark & Sweep GC(CMS GC)

 CMS GC는 아래와 같은 형식으로 진행이 됩니다. 각 단계를 살펴보면 처음 Initial Mark 단계에서 클래스로더와 가장 가까운 객체 중에 살아있는 객체만을 확인 합니다. 이 단계에서는 Stop-The-World가 발생하며 모든 것을 확인하는 것이 아니기 때문에 다른 스레드들이 멈추는 시간이 적습니다. Concurrent Mark 단계에서는 Initial Mark 단계에서 찾은 객체들이 참조하고 있는 객체들을 찾아 가면서 살아 있는 객체들을 확인 합니다. 이 단계에서는 Stop-The-World가 발생하지 않습니다. 그리고 Remark 단계에서는 Concurrent 단계를 진행 하면서 중간에 새로 참조 되거나 참조가 끊긴 객체들을 확인 합니다. 이 단계에서는 Stop-The-World가 발생 합니다. 그리고 Concurrent Sweep 단계에서는 이제 참조가 되지 않고 있는 객체들에대한 정리를 합니다. 이 단계에서는 다른 스레드들을 멈추지 않고 진행 합니다.


 다른 GC 방식들 보다 Stop-The-World 시간이 적다는 장점을 갖고 있지만 다른 방식보다 메모리와 CPU를 많이 사용한다는 단점이 있고 Compaction 단계가 없다는 특징이 있습니다. 조각난 메모리에대한 Compaction을 해야 할 경우에 다른 GC보다 Stop-The-World 시간이 길어질 수 있습니다. 따라서 얼마나 자주 Compaction을 해야하는지 확인 후 사용해야 합니다.


  • G1 GC
 기존의 GC와 동일한 영역을 사용하지만 유연성이 제공 됩니다. 하나의 영역이 가득 차면 해당 영역에대한 GC를 수행하고 다른 영역에 객체를 할당 합니다. GC 방식은 CMS와 비슷한 방식을 사용하지만 Compaction을 제공한다는 큰 차이점이 있습니다. CMS의 문제점을 해결하기 위해서 개발된 GC 입니다.


 Heap 영역은 동일한 연속된 동일한 크기의 공간으로 나뉘어져 있습니다. 각 영역의 크기는 정해진 것이 아니기 때문에 메모리 영역의 사용에대한 유연성을 제공 할 수 있습니다. GC가 시작되면 G1은 CMS와 비슷한 방식으로 동작 합니다. Heap 메모리에 객체가 살아 있는지 동시적이고 전역적인 마킹을 수행 합니다. 검사가 끝나면 어떤 영역의 메모리가 가장 많이 비어있는지 확인 할 수 있고 그 공간부터 메모리 회수를 시작 합니다. 그렇게 때문에 Garbage First(G1)이라는 이름을 갖고 있는 것 입니다. 그리고 G1에 의해서 교체를 해야 되는 공간은 배출(evacuation)에 의해서 GC를 시작 합니다. 하나 이상의 공간에서 객체를 복사해 다른 공간으로 이동 시킵니다. 이 과정에서 메모리 공간의 최적화가 수행 됩니다. 배출은 멀티 프로세스에 의해서 병렬처리가 되기 때문에 Stop-The-World 시간이 줄어들 수 있습니다.


참고


Comments