윤개발

Java Garbage Collection 이란? 본문

백엔드/Java

Java Garbage Collection 이란?

DEV_SJ 2020. 11. 12. 18:09

Garbage Collection란?

Java에서는 메모리 관리를 명시적으로 해제하지 않고 Garbage Collection(이하 GC)가 자동으로 수행한다.

JVM이 GC를 실행할 때 GC를 실행하는 스레드를 제외한 모든 스레드를 중단하는데 이를 stop-the-world 라고한다.

stop-the-world가 일어나면 다른 스레드가 실행되지 않기 때문에 GC를 튜닝한다는 것은 stop-the-world 시간을 최소화하는데에 있다.

 

GC는 더이상 필요없는 객체(쓰레기)를 정리하는데 GC는 2가지의 가정하에 만들어졌다.

- 대부분의 객체는 금방 접근 불가능한 객체가 된다.

- 오래된 객체(생성된지 오래된)에서 젊은 객체(생성된지 얼마되지 않은)로의 참조는 거의 일어나지 않는다.

 

이러한 가설을 'weak generational hypothesis'라 한다. 이를 바탕으로 Young 영역과 Old 영역으로 나뉘게 된다.

 

GC의 영역

- Young 영역: 생성된 객체는 모두 Young 영역에 위치하게 된다. 이 과정에서 대부분의 객체가 접근 불가능하게 되기 때문에

많은 객체가 GC에의해 소멸된다. 이 영역에서 GC가 발생할 때 minorGC가 발생한다고 한다.

 

- Old 영역 : Young 영역에서 오래동안 GC에 의해 삭제되지 않은 객체들이 오게된다. Young 영역보다 크게 할당하며 GC가 빈번하게 이루어지진 않는다.

Old 영역에서 GC가 발생할때 majorGC(FullGC)가 발생한다고 한다.

 

그렇다면 2번째 가설처럼 Old 영역에서 Young 영역으로의 객체 참조가 이루어진다면 어떻게 될까?

Old 영역은 크기가 크고 GC가 빈번하지 않기 떄문에 Old를 모두 탐색해서 참조중인 Young을 찾는 것은 비효율적이다.

이를 위해 Old 영역에서는 Card Tabel을 사용한다.

 

카드 테이블에서는 Old -> Young 으로 참조가 일어날때만 정보가 기록된다.

결국 Young으로의 참조가 있는지는 전체탐색 할 필요 없이 Card Table만 탐색하면된다.

 

Young 영역의 GC

 - eden 영역

 - survivor 영역 (2개)

1. 객체가 생성되면 일단 Young 영역의 eden 영역에 객체가 저장된다.

2. Young 영역에서 GC가 일어나고 살아남은 객체들은 하나의 survivor 영역으로 이동한다.

3. 하나의 survivor 영역이 가득차면 GC가 이루어지게 되고 살아남은 객체들은 다른 survivor 영역으로 이동한다.

   ( 2개중 하나의 survior 영역은 항상 비어있는 것이다.)

4, survivor 영역을 번갈아 가며 이동하다 오래 살아남은 객체는 Old 영역으로 이동한다.

 

Old 영역의 GC

Old 영역은 데이터가 가득 차면 GC를 실행한다. Old 영역의 GC는 여러가지 방식이 있다.

 

1. Serial GC - Old 영역에서 살아남은 객체들을 마킹하고 살아남은 객체들을 순서대로 채운다.

                 CPU의 코어가 1개이고 메모리가 적을때 사용한다. 순서대로 진행되어 시간이 오래걸린다.

 

2. Parrel Serial GC - Serial GC와 같지만 다중코어일시 사용한다. 다중 스레드가 GC를 수행하여 Serial GC보다 빠르다.

 

3. CMS GC - CMS의 초기 단계에서는 살아있는 객체를 탐색하는 것으로 끝낸다. 따라서 stop-the-world 시간이 짧다.

                 다음 단계에서는 살아있는 객체들과 연결된 객체들을 탐색한다. 이 과정은 다른 스레드와 동시에 진행된다.

                 마지막으로 쓰레기들을 정리한다. 이 작업 또한 다른스레드와 동시에 진행된다.

                 이로 인해 CMS는 CPU와 메모리를 더 많이 사용한다.

마무리

각 서비스의 WAS에서 생성하는 객체의 크기와 생존 주기가 모두 다르고, 장비의 종류도 다양하다.

지속적인 튜닝과 모니터링을 통해서 해당 서비스에 가장 적합한 GC 알고리즘을 찾아야한다. 

 

참조

https://d2.naver.com/helloworld/1329

'백엔드 > Java' 카테고리의 다른 글

DIP 아키텍처 설계  (0) 2021.08.03
Java의 Equals와 Hashcode  (1) 2021.04.27
Comments