본문 바로가기
프로그래밍과 자료구조

[프로그래밍] JVM의 Garbage Collection

by 뜨는 해 2020. 10. 23.

 

자바를 사용하는 입장에 있어서 Garbage Collection(이하 GC)는 몰라서는 안될 개념이라고 생각한다.

 

C 계열 언어를 전문적으로 써본 적은 없어서 잘 모르겠지만, 메모리 관리를 프로그래머가 직접 메모리에 접근해 불필요한 자원을 해제 해줘야하는 불편함이 있다. 하지만 자바는 굳이 직접 프로그래머가 하지 않는데 이 이유는 GC가 존재하기 때문이다.

 

정의를 보자면,


메모리 관리 기법 중의 하나로, 프로그램이 동적으로 할당했던 메모리 영역 중에서 필요없게 된 영역을 해제하는 기능이다. 영어를 그대로 읽어 가비지 컬렉션이라 부르기도 한다. 1959년 무렵 리스프의 문제를 해결하기 위해 존 매카시가 개발하였다.

 

정의를 보면 알겠지만 GC는 자바에서 최초 적용된 것이 아니라 LISP에서 최초로 적용되었다는 것을 알 수 있다.

 

아무튼 그렇다면 GC는 어떤식으로 동작하게 될까?

 

Garbage Collector의 동작 방식


GC가 가지는 기본 전제 조건은 이렇게 있다고 한다.

 

  • 대부분의 객체는 금방 접근 불가능(Unreachable) 상태로 변한다.

  • 오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다. -> (사실 나는 이 의미가 크게 와닿지 않는다.. 실무를 겪어보지 않아서 그런가)

먼저 용어를 정리하자면

Major GC는 Old Generation에서 발생하는 GC.

Minor GC는 Young Generation에서 발생하는 GC 라고 한다.

 

GC가 작동하게 될 경우 프로그램이 멈추게 되는데 이것을 'STW - Stop-The-World'라고 부른다.

프로그램을 최적화 하기 위해서는 이러한 STW를 적게 발생시키도록 최적화 한다고 한다.

 

이러한 개념을 전제로 만들어진 JVM중 Oracle사의 'HotSpot JVM'이 가장 일반적이면서도 강력하다고 한다.

 

그래서 HotSpot JVM에서는 물리적은 2가지의 영역을 가지게 되는데 이것들을 각각 'Young Generation 영역''Old Generation 영역'으로 나뉘게 된다.

 

이러한 Young 영역에서는 많은 객체들이 생성되고 사라지게 된다. 이는 곧 개념 중 하나인 객체가 금방 접근 불가능이 되는 것과 관련이 있다. -> Minor GC가 동작함.

 

Old 영역에서는 Young 영역에서 살아남은 객체들이 복사되는 곳으로 Young 영역보다 큰 공간을 가지고 있다고 한다. -> Major GC가 동작함.

 

사진을 보면 알겠지만, Young과 Old 영역 이외에도 Permanant Generation 영역이 있는 것을 볼 수 있는데, 이 곳은 클래스나 매서드 같은 메타 데이터가 저장된다고 한다. 그렇다고 GC가 Permanant 영역에서 작동되지 않는다고 하냐면 그것도 아니다. 더 이상 사용되지 않는 클래스의 경우는 GC의 수집 대상이 될 수 있다고 한다.

 

 

GC의 Young Generation 영역


 

GC의 Young 영역에서는 크게 3가지의 세부 영역을 가지게 되는데 이는 Eden, Survivor 0, Survivor 1 이렇게 나뉘게 된다.

 

과정을 보자면,

 

  1. 새로 생성된 객체는 Eden 영역에 저장되게 된다.

  2. 이러한 Eden 영역이 가득차게 될 경우 Minor GC가 발생된다.

  3. MinorGC 발생 이후 살아남은 객체, 즉 접근 가능한(Reachable) 객체는 Survivor 0으로 옮겨지게 된다.

  4. 2번과 같은 수행이 또 일어나게 되면, Survivor 0에 있던 객체는 Survivor 1로 옮겨지게 되고, Eden에서부터 살아남은 객체들이 Survivor 0에 저장되게 된다. -> 이러한 Survivor 영역을 드나들 때 마다 age가 쌓이게 된다.

  5. 이렇게 age가 쌓이고 계속 살아남은 객체들은 일정한 age 조건을 만족하면 Old Generation 영역으로 보내지게 되는데 이것을 'Promotion' 이라고 한다. (승진했네...)

  6. 이러한 Minor GC의 작업과 계속된 Promotion이 진행되면 Old Generation 영역도 가득 차게 될 것이고 이렇게 된다면 Major GC를 발생시킨다.

 

GC의 Old Generation 영역


Old Generation은 기본적으로 Young Generation에서 'Promotion' 된 객체들을 저장하는 공간이다.

 

언젠가 Old 영역도 가득차게 될 것이고 이를 해결하기 위한 여러가지 기법이 있다고 한다.

 

  • Serial GC

  • Parallel GC

  • Concurrent Mark & Sweep GC (CMS)

  • G1 GC

등이 있다고 한다.

 

하지만 아직 이러한 기법을 공부하기에는 미숙한 것 같고 나중에 공부를 다 마치면 자세하게 리뷰해볼 예정이다.

 


앞서 GC를 알아봤는데 사실 GC가 그냥 메모리 관리를 자동적으로 해준다는 것만 알았지, 이런식으로 동작하고 메모리를 관리 하는지를 잘 몰랐다.

 

어떤 사람들은 이렇게 자동으로 메모리를 관리하는 GC에 대해 오히려 불편함을 호소하는 경우도 있다고 한다.

 

내가 아직 실무를 접해보지 못해 잘은 모르겠지만 프로그램의 성능 최적화를 위해 Minor GC와 Major GC를 튜닝하는 경우도 있다고 하니, 실제로 튜닝을 해본다면 재밌을 것 같다는 생각이 든다.