본문 바로가기

Java

GC(Garbage Collection, Garbage Collector)

Garbage Collection 이란

 

Garbage Collection 이란 JVM의 Heap 영역에서 사용하지 않는 객체를 삭제하는 프로세스를 말한다.

 

JVM 구조

JVM의 Heap 영역에는 자바 프로그램을 실행하면서 생성된 모든 객체가 저장된다. 메모리 공간은 한정적이기 때문에 더 이상 쓰지 않는 객체를 제때 정리하지 않는다면 Out Of Memery Error (OOM)가 발생한다. 이를 막기 위해 JVM에는 자동으로 메모리 관리를 해주는 Garbage Collector가 존재한다.

 

* C언어를 사용해본 사람이라면 free라는 명령어를 통해 직접 메모리를 해제해본 경험이 있을 것이다. 하지만 자바에서는 이 과정이 JVM에 의해 자동으로 일어난다.

 


GC 동작 순서

 

GC 동작 순서는 다음과 같다.

  1. GC 수거 대상 확인(Mark)
  2. Mark 되지 않은 객체 제거(Sweep)
  3. 분산된 메모리 정리(Compact) – 이건 필수가 아니라 옵션

GC 동작하기 전과 후 모습

 


Mark And Sweep (And Compact)

 

Mark : 사용되는 메모리와 사용되지 않는 메모리를 식별하는 작업

Sweep : Mark 단계에서 사용되지 않음으로 식별된 메모리를 해제하는 작업

Compact : Sweep으로 발생한 메모리 단편화를 해결하기 위해 메모리를 정리하는 작업(필수가 아니라 옵션)

 


GC Root(GC 수거 대상 판단 기준)

 

힙 영역에서 수거 대상인 객체를 판단하려면 그 기준이 필요하다. 이때 기준으로 사용되는 객체가 바로 GC Root인데 GC Root로부터 참조 관계가 존재하지 않는 객체는 Heap 영역에서 제거된다. GC Root가 될 수 있는 조건은 다음과 같다.

  • Stack 영역의 데이터
  • Method 영역의 Static 데이터
  • JNI에 의해 생성된 객체

Garbage Collection 수행 영역 구분

 

 

Heap 영역은 다음과 같이 구분할 수 있다.

  • Young Generation 영역
    - 새로운 객체들이 할당되는 영역
    - 대부분의 객체는 오랫동안 참조되지 않기 때문에 대부분의 객체는 Yong Generation 영역에 생성되었다가 금방 GC 대상이 된다.
    - 이 영역에서 객체가 사라질 때 Minor GC가 발생했다고 한다.

  • Old Generation 영역
    - Young Generation에서 오랫동안 살아남은 객체들이 존재하는 영역
    - 대부분 Young 영역보다 크게 할당하며, 크기가 큰 만큼 Young 영역보다 GC는 적게 발생한다.
    - 이 영역에서 객체가 사라질 때 Major GC(혹은 Full GC)가 발생했다고 한다.


Garbage Collection 발생 시나리오

 

객체가 생성되면 Eden 영역에 위치 하게 된다.

 

Eden 영역이 가득차게 되면 Minor GC가 발생하여 참조가 없는 객체는 삭제되고, 참조 중인 객체는 Survivor 영역으로 이동한다.

 

Survivor 영역 둘 중 하나는 반드시 비어있어야 한다. Minor GC가 발생할 때마다 살아남은 객체들은 두 Survivor 영역 중 한 곳으로 이동한다. 그리고 살아남의 객체의 age bit는 1씩 증가한다.

 

Survivor 영역에서의 GC과정을 반복하며, 오랫동안 살아남은 객체는 Old Generation으로 이동한다.

 

Eden 영역에서 Survivor 영역으로 이동할 때 객체가 남아있는 영역보다 큰 경우 Old Generation으로 이동한다.

 

* Minor GC에서 살아남은 객체는 age bit를 갖게 되는데 age bit가 일정 값을 넘어가게 되면 오랫동안 살아남은 객체로 판단되어 Young Generation 영역에서 Old Generation 영역으로 넘어간다. 이때 Young Generation 에서 Old Generation으로 이동하는 과정을 Promotion 이라고 한다.

 


Stop The World

 

Stop The World는 Garbage Collection을 실행하기 위해 JVM이 애플리케이션의 실행을 멈추는 작업이다. GC가 실행될 때는 GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업이 중단되고, GC가 완료되면 작업이 재개된다. 당연히 모든 쓰레드들의 작업이 중단되면 애플리케이션이 멈추기 때문에, GC의 성능 개선을 위해 튜닝을 한다고 하면 보통 stop-the-world의 시간을 줄이는 작업을 하는 것이다. 또한 JVM에서도 이러한 문제를 해결하기 위해 다양한 실행 옵션을 제공하고 있다.

 


Garbage Collector  종류

 

현재 JVM에는 다음과 같은 Garbage Collector가 있다.

  • Serial GC
  • Parallel GC
  • Parallel Old GC
  • CMS(Concurrent Mark Sweep) GC
  • G1 GC
  • Z GC

 

Serial GC

  • 가장 단순한 방식의 GC로 싱글 스레드(스레드 1개)로 동작한다.
  • 싱글 스레드로 동작하기 때문에 느리고, 그만큼 Stop The World 시간이 다른 GC에 비해 길다.
  • Mark & Sweep & Compact 알고리즘을 사용한다.
  • GC가 동작할 때 어플리케이션의 모든 스레드를 멈추기 때문에 멀티스레드 어플리케이션에 사용하기에 적합하지 않다. 보통 실무에서 사용하지 않는 GC이다. (디바이스 성능이 안 좋아서 CPU 코어가 1개인 경우에만 사용)

 

 

Parallel GC

  • Java 8의 default GC
  • Young 영역의 GC를 멀티 스레드 방식을 사용하기 때문에, Serial GC에 비해 상대적으로 Stop The World 가 짧다.

 

 

Parallel Old GC

  • Parallel GC는 Young 영역에 대해서만 멀티 스레드 방식을 사용했다면, Parallel Old GC는 Old 영역까지 멀티스레드 방식을 사용한다.

 

 

CMS(Concurrent Mark Sweep) GC - Deprecated

  • 어플리케이션의 스레드와 GC 스레드가 동시에 실행되어 stop-the-world 시간을 최대한 줄이기 위해 고안된 GC
  • GC 과정이 매우 복잡함
  • GC 대상을 파악하는 과정이 복잡한 여러 단계로 수행되기 때문에 다른 GC 대비 CPU 사용량이 높다.
  • CMS GC는 Java9 버전부터 deprecated 되었고 결국 Java14에서는 사용이 중지됨

 

 

G1(Garbage First) GC

  • Java 9+ 의 default GC
  • 기존의 GC 알고리즘에서는 Heap 영역을 물리적으로 고정된 Young / Old 영역으로 나누어 사용하였지만, G1 GC는 아예 이러한 개념을 뒤엎는 Region이라는 개념을 새로 도입하여 사용.
  • 전체 Heap 영역을 Region이라는 영역으로 체스같이 분할하여 상황에 따라 Eden, Survivor, Old 등 역할을 고정이 아닌 동적으로 부여함
  • 전체 Heap에 대해서 탐색하지 않고 Region 단위로 탐색하여, 각각의 Region에만 GC가 발생한다.
  • Garbage로 가득 찬 영역을 빠르게 회수하여 빈 공간을 확보하므로, 결국 GC 빈도가 줄어드는 효과를 얻게 되는 원리

 

 

ZGC

  • 대량의 메모리(8MB ~ 16TB)를 low-latency로 잘 처리하기 위해 디자인 된 GC
  • G1의 Region 처럼 ZGC는 ZPage라는 영역을 사용함
  • G1의 Region은 크기가 고정인 반면 ZPage는 2mb 배수로 동적으로 운영됨.
  • ZGC의 최대 장점 중 하나는 힙 크기가 증가하더도 stop-the-world의 시간이 절대 10ms를 넘지 않는다는 것

 


출처 : 
https://www.youtube.com/watch?v=FMUpVA0Vvjw&t=625s
https://www.youtube.com/watch?v=8JrciOSL3Gk
https://www.youtube.com/watch?v=Fe3TVCEJhzo
https://jhyonhyon.tistory.com/20
https://velog.io/@jeb1225/Java%EC%9D%98-GC-%EC%9D%B4%ED%95%B4
https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98GC-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%F0%9F%92%AF-%EC%B4%9D%EC%A0%95%EB%A6%AC#zgc_%EC%8B%A4%ED%96%89_%EB%AA%85%EB%A0%B9%EC%96%B4

'Java' 카테고리의 다른 글

BigDecimal  (0) 2024.05.20
String과 String Constant Pool  (0) 2024.03.26
상수(Constant)와 리터럴(Literal)  (0) 2024.03.17
JVM 구조  (0) 2023.10.22
에러(Error)와 예외(Exception)  (1) 2023.09.04