GC에 대해서

이동엽·2025년 9월 28일

GC, 가비지 컬렉터는 Heap 영역에서 사용하지 않는 객체 메모리를 자동으로 회수하고 관리해준다.
이거 덕분에 개발자는 직접 메모리를 관리 하는게 아닌 자동으로 해준다.

MinorGC, Major GC

JVM의 Heap 영역은 처음 설계 될때 2가지 전제로 설계되어있다.

  • 대부분의 객체는 금방 접근 불가능한 상태(Unreachable)가 된다.
  • 오래된 객체에서 새로운 객체로의 참조는 아주 적게 존재한다.

즉, 객체는 대부분 일회성, 오랫동안 남아있는 경우가 드물다. 그래서 객체가 존재하는 기간에 따라 Heap 영역을 나누게 되고, Young, Old 로 설계되었습니다.

GC영역

Young 영역

  • 새롭게 생성된 객체가 할당 되는 영역

  • 대부분의 객체가 금방 Unreachable 상태가 되기 때문에, 금방 생성되었다가 사라진다.

  • 여기에 대한 GC를 Minor GC라고 부른다.

Old 영역

  • Young영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역

  • Young 영역보다 크게 할당되며, 영역의 크기가 큰 만큼 가비지는 적게 발생한다.

  • Old 영역에 대한 가비지 컬렉션(Garbage Collection)을 Major GC라고 부른다.

왜 크게 할당 되냐?
-> Young 영역은 수명도 짧고 큰공간이 필요없다, 큰 객체들은 바로 Old 영역에 할당된다.
!! 예외론 Old 영역의 객체가 Young 영역의 객체를 참조하는 경우
이걸 대비해서 Old영역에 512 bytes로 되어있는 카드 테이블로 되어있다.

여기엔 Old 영역에 있는 객체가 Young 영역의 객체를 참조할 때 마다 그에 대한 정보가 표시된다.
이걸로 인해 Young 영역에서 가비지 컬렉션이 진행될 때 카드 테이블만 조회하여 GC의 대상인지 식별할 수 있도록 하고 있다.

동작 방식

이것 뿐만 아니라 전체 애플리케이션의 안정성과 성능에 직결되는 핵심 기능이다.
그러나, GC가 실행되면 JVM은 일시적으로 애플리케이션을 멈춘다(Stop-The-World) 이시간엔 모든 쓰레드가 멈추고, 이 작업이 완료되면 애플리케이션이 다시 작동한다.

그래서 무작정 작동하게 하면 성능 저하가 올수도 있다.

Stop The World

이시간엔 모든 쓰레드가 멈추고, 이 작업이 완료되면 애플리케이션이 다시 작동한다.
GC가 실행될 때는 GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업이 중단되고, 중단되면 애플리케이션이 멈추고, GC가 완료되면 작업이 재개된다.

그래서 GC 성능 개선을 한다면? 보통 stop the word 이 시간을 줄이는 작업을한다.

Mark and Sweep

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

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

이시간엔 스택의 모든 변수 또는 접근 가능한 객체들을 스캔하면서 각각 어떤 객체를 참고하는지를 탐색하고, 사용되는 메모리를 식별하는데에 이 과정을 Mark.
이후에 식별 안된 객체들을 메모리에서 제거하는데 이 과정이 Sweep 이라고 한다.

Minor GC 동작방식

Minor GC는 Young 영역에서 일어나는 GC다.
모든 객체는 처음엔 Young 영역에 생성된다.
이 Young 영역에선 3가지로 나눠진다.

Eden 영역 : 새로 생성된 객체가 할당되는 영역
Survivor 영역(0,1) : 최소 1번 GC이상 에서 살아 남은 객체가 존재하는 영역

Survivor 영역에는 특별한 규칙이 있는데, Survivor 0 또는 Survivor 1 둘 중 하나에는 꼭 비어 있어야 하는 것이다.

GC 과정

  1. 처음 생성된 객체는 Eden 영역에 할당

  2. 객체가 계속 생성되서 Eden 영역이 꽉차게 되면 Minor GC 실행

  3. Mark 동작으로 읽을수 있는 객체 탐색

  4. Eden 영역에서 살아남은 객체는 Survivor 0 영역으로 이동

  5. Eden 영역에서 사용 안하는 객체 메모리를 해제

  6. 살아 남은 모든 객체들은 age값 1씩 증가

  7. 이후 같은 프로세스 실행후 살아 남은 객체들을 Survivor 1로 이동후 sweep

  8. 모든 객체들 age 값 1씩 증가. 및 이 과정 반복

여기서 Survivor 0,1은 이 과정을 반복되면서 0->1, 1->0 이렇게 이동이 된다.
그리고 계속 살아 남는 객체는 Old 영역으로 이동한다.

Major GC 과정

여기는 계속 객체들이 이동되서 Old 영역의 메모리가 부족해지면 발생한다.
기본적으로 mard and sweep 방식으로 동작합니다.

기본적으로 공간이 Young 영역보다 크기 때문에 수행 시간이 훨씬 오래 걸리고, 일반적으로 Minor GC 같은경우 0.5-1초, Major GC는 대비 10배 이상 소요된다고 합니다.

그래서 Minor GC는 애플리케이션에 크게 영향을 주지않지만,

Major GC 는 Thread가 멈추고 Mark and Sweep 작업을 해야하기 때문에, CPU에 부하가 가기에 멈추고 버벅이는 현상이 나타난다.
이문제가 Stop-The World

그래서 GC 알고리즘이 여러가지가 있습니다.

참고

https://youwjune.tistory.com/57

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

profile
씨앗

0개의 댓글