JAVA

[Java] Garbage Collection (가비지 컬렉션)

혀내 2023. 6. 25. 16:12
반응형

가비지 컬렉션에 앞서, 간단히 JVM 구조를 톺아보자.

 

HotSpot JVM Architecture

HotSpot JVM은 가장 일반적으로 사용되는 JVM으로 JIT 컴파일러가 자바 프로그램 실행 중에도 동적으로 최적화를 제공하고, 멀티 스레드 환경에서도 GC가 동작하는 등 다양한 방식으로 높은 성능과 가용성을 보장한다.

 

 

HotSpot JVM의 구조는 다음과 같다.

 

출처: 오라클

 

여기서 Heap은 객체 데이터가 저장되는 공간이자 Garbage Collector에 의해 메모리가 관리되는 공간이다. 사용하는 Garbage Collector의 타입에 따라 다른 방식으로 메모리가 최적화된다.

 

 

 

Garbage Collection 이란?

자바는 다른 언어와 달리 JVM에 탑재되어 있는 Garbage Collector가 힙의 메모리를 자동으로 관리해주기 때문에, 개발자가 별도로 메모리 관리에 크게 신경을 기울일 필요가 없다. 즉, C/C++에서는 malloc()free()로 개발자가 메모리를 할당하고 해제했다면, 자바에서는 System.gc() 메서드를 호출해 명시적으로 메모리를 지정하거나, free()로 해제하지 않는 것이 좋다. 개발자를 대신해서 Garbage Collector가 더 이상 참조되지 않는 객체들을 찾아 메모리에서 해제하는 작업을 수행한다.

 

 

mark-sweep-compact

GC의 가장 기본적인 알고리즘이다. 대부분의 GC는 이 알고리즘을 기반하여 메모리를 최적화한다.

 

 

1. Mark: (Old 영역에) 살아있는 객체를 식별한다.

 

출처: 오라클

2. Sweep: 힙의 앞 부분부터 확인하여 살아 있는 것만 남긴다.

 

출처: 오라클

3. Compaction: 객체들이 연속되게 쌓이도록 힙의 가장 앞 부분부터 채워 객체가 존재하는 부분과 없는 부분으로 나눈다.

 

출처: 오라클

 

 

 

 

모든 객체들을 위와 같은 알고리즘으로 관리하면 GC에 너무 많은 시간이 소요되어 성능이 저하된다. 여러 JVM 연구를 통해 대부분의 객체는 매우 짧은 시간 동안 참조된다는 사실이 발견되었고 이 점을 활용하고자 Hotspot 힙 영역을 Young 영역과 Old 영역이라는 두 개의 물리적 공간으로 구분하였다.

 

 

출처: 오라클

 

1. Young Generation 영역

 새롭게 생성한 객체들이 할당되는 영역이다. 이 영역이 가득 차면 Minor GC가 발생한다. 대부분의 객체가 금방 접근 불가능(unreachable) 상태가 되기 때문에 보통 Young 영역에 생성되었다가 사라진다. GC가 여러 번 수행된 뒤에도 Young 영역에서 살아남은 객체는 Old 영역으로 이동한다.

 

 

2. Stop the World 이벤트

 모든 GC는 stop-the-world 이벤트를 동반한다. GC가 시작되면 GC를 실행중인 스레드를 제외하고 모든 스레드가 중지된다. GC가 끝나면 다시 멈췄던 스레드를 정상 실행한다. GC 튜닝은 즉, stop-the-world에 인해 정지되는 시간을 최소화하는 과정을 일컫는다.

 

 

3. Old Generation 영역

 오래 살아남은 객체들이 할당되는 영역이다. Old 영역이 가득 차면 Majo GC가 발생한다. 대부분 Young 영역보다 크게 할당하기 때문에 크기가 큰 만큼 Young 영역보다 GC가 적게 발생하고, GC에 더 오랜 시간이 걸린다. 

 

 

4. Parmenent 영역

 JVM이 애플리케이션에서 클래스나 메서드를 정의하기 위해 필요한 메타 데이터들이 할당되는 영역이다. Java SE 라이브러리 데이터나 애플리케이션에서 사용되는 클래스 데이터가 여기에 저장된다. 다른 클래스에서 더 이상 사용되지 않는 클래스들은 JVM에 의해 로딩되지 않으므로 이 영역 또한 Major GC 영역에 포함된다.

 

 

 

Old 영역에 있는 객체가 Young 영역의 객체를 참조할 때

Old 영역에는 512바이트의 덩어리로 되어있는 카드 테이블이 존재하며 Old 영역에 있는 객체가 Young 영역의 객체를 참조할 때마다 정보가 여기에 표시된다. Minor GC를 실행할 때, 이 카드 테이블을 함께 뒤지면서 객체가 GC 대상인지 식별한다.

 

 

 

 

GC Process

일반적인 GC 프로세스를 알아보며 왜 힙 영역이 Young과 Old 영역으로 나뉘어져 있고, Young 영역은 다시 Eden과 Survivor로 분리되는지 이해해보자.

 

 

1. 새로 생성된 객체는 Eden 영역에 위치한다.

출처: 오라클

 

2. Eden 영역이 꽉 차면 Minor GC가 발생한다.

출처: 오라클

 

 

3. GC가 한 번 발생하고 살아남은 객체는 첫 번째 Survivor 영역(S0)으로 이동한다. 참조되지 않는 객체들은 에덴 영역에서 삭제된다.

 

출처: 오라클

 

 

4. 다음 Minor GC이 발생하면 같은 과정이 반복된다. 이 때, Eden에서 살아남은 객체들은 두 번째 Survivor 영역(S1)으로 이동한다. S0 영역에서 살아남은 객체들도 S1 영역으로 이동한다.

출처: 오라클

 

 

정상적인 GC 상태라면, 이번 Minor GC가 끝난 다음에는 Eden 영역과 S0 영역이 모두 비어있어야 한다.

 

 

 

5. 다음 Minor GC에서도 같은 과정이 반복된다. 여기서 살아남은 객체들은 S0 영역으로 이동한다.

출처: 오라클

 

 

 

6. 여러 번의 Minor GC에도 살아남은 객체들은 Young 영역에서 Old 영역으로 이동한다.

출처: 오라클

 

 

 

8. 이 절차가 반복되다 old 영역이 가득 차면 Major GC가 발생한다.

출처: 오라클

 

 

 

 

 

 

Garbage Collector 종류

GC 방식은 JDK 7 기준으로 4가지가 있다.

 

1. Serial GC 

Young 영역에서는 앞에서 설명한 방식을, Old 영역에서는 mark-sweep-compact 알고리즘을 사용한다. CPU 코어가 하나만 있을 때 사용하기 위해 만들어진 방식으로 Minor GC와 Major GC가 순차적으로 실행된다. 적은 메모리와 CPU 코어 개수에 적합한 방식으로 운영서버에서는 절대 Serial GC를 사용하지 않아야 한다.

 

 

2. Parallel GC

Serial GC와 기본적인 알고리즘은 같으나 CPU가 N개 일 때 사용하기 적합한 방식이다. 스레드 개수만큼 N개의 GC가 동작한다. 빠르게 객체를 처리할 수 있으며 메모리가 충분하고 코어 개수가 많을 때 유리하다.

 

 

3. CMS(Concurrent Mark Sweep) GC

초기 Initial Mark 단계에서는 클래스 로더에서 가장 가까운 객체 중 살아 있는 객체만 찾는다. Concurrent Mark 단계에서는 방금 살아있다고 확인한 객체에서 참조하는 객체들을 따라가면서 확인한다. 이 때 다른 스레드가 실행 중인 상태에서 동시에 진행된다. Remark 단계에서는 Concurrent Mark 단계에서 새로 추가되거나 참조가 끊긴 객체를 확인한다. 마지막으로 Concurrent Sweep 단계에서는 쓰레기를 정리하는 작업을 실행한다.

 

GC에 의해 애플리케이션이 중지되는 시간이 줄이기 위해 mark-sweep-compact 알고리즘 중 compact 단계를 실행하지 않는다. 이로 인해 단편화가 발생할 수 있으므로 CMS GC를 사용한다면 매우 큰 Heap 영역을 사용할 것을 권장한다. stop-the-world 시간이 매우 짧아, 모든 애플리케이션의 응답 속도가 매우 중요할 때 CMS GC를 사용한다. 반면에 다른 GC 방식보다 메모리와 CPU를 더 많이 사용하기에 신중한 검토 후에 사용 여부를 결정해야 한다.

 

 

4. G1 GC

CMS GC를 장기간 대체하기 위해 만들어진 GC 방식이다. 바둑판의 각 영역에 객체를 할당하고 GC를 실행하다 해당 영역이 꽉 차면 다른 영역에서 객체를 할당하고 GC를 실행한다. 기존의 힙 구조와 달리 Young, Old 영역을 명확히 구분하지 않고 일정 크기의 논리적 단위인 Region으로 구분한다. G1 GC는 그 어떤 방식보다도 빠르다는 장점이 있다.

 

출처: 오라클

 

 

 

 

 

 

 

 

 

 

참고 자료:

https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

https://mangkyu.tistory.com/118

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

 

반응형