[JAVA] 가비지 컬렉션(Garbage Collector)이란?

sammy·2023년 10월 12일

백엔드 공부

목록 보기
2/2

가비지 컬렉터(Garbage Collector)

1. 가비지 컬렉터? 그게 뭔데??

가비지 컬렉션은 GC라고도 부르며 가비지 컬렉션을 해주는 친구입니다. 가비지 컬렉션은 쓰레기 수집이라는 뜻입니다. 우리가 자바 프로그래밍을 하면서 힙 영역에 동적으로 메모리를 할당해주는 역할을 하는 new 키워드를 자주 사용하게 됩니다. C언어에서는 malloc 함수를 통해 할당한 메모리를 free 함수를 통해 메모리에서 해제해 주어야 하는데 이러한 메모리 해제 작업을 자바의 GC가 자동으로 해준다고 생각하면 됩니다.

// 1번 예시
Book book = new Book();
book.setTitle("Python");
book = null;

// 기존의 제목을 Python으로 생성한 book 객체는 더이상 참조가 없고, 가비지가 됨
book = new Book();
book.setTitle("JAVA");
// 2번 예시
for (int i = 0; i < 10; i++) {
  Book book = new Book(); 
  book.doSomething();
}

객체들은 실질적으로 Heap 영역에서 생성되고 Method, Stack 영역에서는 이렇게 Heap 영역에 생성된 객체들을 참조하는 형식으로 구성됩니다. 위 1번 예시와 같이 객체를 참조하고 있던 변수가 다른 객체를 참조하게 되면 기존 객체는 Heap 영역에서 어디서든 참조하고 있지 않은 객체가 됩니다. 혹은, 2번 예시 같이 for문 밖에서는 더이상 사용할일이 없어질 때, 이러한 객체들을 Unreachable(객체가 참조되고 있지 않은 상태)하다 표현하며 GC에 의해 제거됩니다.

2. 개념은👌 그럼 언제 동작하는데?

GC는 JVM에 올라가기 때문에 기본적으로 런타임에 동작하며, 다음과 같은 몇가지 조건들 중 하나라도 충족되면 JVM은 GC를 실행합니다.

  1. OS로부터 할당 받은 시스템의 메모리가 부족할 때
  2. 관리하고 있는 힙에서 사용되는 메모리가 허용된 임계값을 초과했을 때
  3. 프로그래머가 직접 GC를 실행하는 경우(System.gc() 하지만, 되도록 사용하지 않는 것이 좋음)

3. GC 이녀석.. 대체 어떻게 동작하는거지? 🤷🏻‍♂️

GC에서 중요한 포인트는 Stop The World입니다.

"stop the world"를 직역하면 세상을 멈춘다??
이는 JVM이 GC를 실행하는 동안 GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업을 일시적으로 중단시킨다는 것을 의미합니다. 그리고 GC가 끝난 후에 일시중지 됐던 쓰레드들이 다시 동작합니다.

GC의 동작을 보기에 앞서 먼저 JVM의 Young 영역과 Old 영역을 이해해야합니다.

3-1. Young 영역과 Old 영역이 뭐지??

  • Young 영역(Yong Generation 영역): 새롭게 생성한 객체의 대부분이 여기에 위치합니다. 대부분의 객체가 금방 접근 불가능 상태가 되기 때문에 매우 많은 객체가 Young 영역에 생성되었다가 사라집니다. 이 영역에서 객체가 사라질때 Minor GC가 발생한다고 말합니다.

  • Old 영역(Old Generation 영역): 접근 불가능 상태로 되지 않아 Young 영역에서 살아남은 객체가 여기로 복사됩니다. 대부분 Young 영역보다 크게 할당하며, 크기가 큰 만큼 Young 영역보다 GC는 적게 발생합니다. 이 영역에서 객체가 사라질 때 Major GC 혹은 Full GC가 발생한다고 말합니다.

💡 그렇다면 JVM은 왜 이렇게 영역을 나눠뒀을까?

JVM에서 Young 영역과 Old 영역을 나누는 주요 목적은 메모리 관리를 효율적으로 수행하고 GC 프로세스를 최적화하기 위해입니다.

  • 객체 수명 주기에 따른 분류
    대부분의 객체는 생성 직후에 더 이상 참조되지 않고 짧은 수명 주기를 가집니다. 이러한 객체들은 Young 영역으로 할당되고, 빈번한 Minor GC로 빠르게 수집됩니다. 반면, 일부 객체는 오래동안 유지되며 장기적으로 사용되는데, 이러한 객체들은 Old 영역으로 이동하게 됩니다.

3-2. Young 영역과 Old 영역의 구성??

이미지 출처: https://steemit.com/kr/@parkjp/java-garbage-collection-gc

  • Young 영역의 구성:

    • Eden 영역
    • Survivor 영역(2개)
  • Young 영역 GC 동작

    • 새로 생성한 대부분의 객체는 Eden 영역에 위치합니다.
    • Minor GC가 한 번 발생한 후, Eden과 Survivor1에 살아남은 객체를 Survivor2로 복사한다. 그리고 살아남지 못한 객체가 남아있는 Survivor1과 Eden 영역을 클리어한다.
    • 다음번 Minor GC가 발생하면 같은 원리로 Eden과 Survivor2 영역에서 살아남은 객체를 Survivor1으로 복사한다.
    • 해당 과정이 반복되면서 살아남은 객체들은 1살씩 먹게되고,계속해서 살아남아 있는 객체는 Old 영역으로 이동하게 됩니다. 이때 몇 살 먹으면 Old 영역으로 가야하는지는 설정해줄 수 있습니다.
  • Old 영역의 구성 및 GC 동작

    • Old 영역에는 여러 번의 Minor GC를 버티고 살아남은 객체들이 있습니다. 이 영역에서 메모리가 가득차게 되면 Major GC가 발생합니다.
    • Major GC는 Minor GC에 비해 많은 시간이 걸립니다.

이미지 출처: https://d2.naver.com/helloworld/1329

Young 영역은 Old 영역보다 일반적으로 크기가 작기 때문에 Minor GC가 보통 0.5~1초 사이에 끝나는 매우 빠른 속도로 애플리케이션에 거의 영향을 주지 않습니다. 하지만, Major GC는 살아 있는 모든 객체를 검사해야 할 뿐만 아니라, Young 영역을 참조할 수도 있기 때문에 오랜 시간이 걸립니다. 이렇게 Major GC가 일어나면 "stop the world" 특징 때문에 애플리케이션이 아무런 동작을 할 수 없기 때문에 Major GC가 일어나는 횟수를 최소화 해야합니다. GC가 동작하는 시간은 GC의 전략에 따라 다르기 때문에 적절한 튜닝이 필요합니다.


참고
https://mangkyu.tistory.com/118
https://readystory.tistory.com/48
https://mirinae312.github.io/develop/2018/06/04/jvm_gc.html
https://d2.naver.com/helloworld/1329

profile
누군가에게 도움을 주기 위한 개발자로 성장하고 싶습니다.

0개의 댓글