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

hyunoi·2024년 11월 4일
0

Java

목록 보기
1/20
post-thumbnail

가비지 컬렉션 (Garbage Collection)


자바의 메모리 관리 기법 중 하나로, JVM의 heap 영역에서 동적으로 할당했던 메모리 영역 중 필요 없게 된 메모리 객체를 주기적으로 제거하는 프로세스이다.

매번 free() 메소드를 사용하여 메모리를 비워주어야 하는 C, C+과 달리 자바는 JVM의 가비지 컬렉터가 메모리 관리를 대신 해준다.

가비지 컬렉션을 사용하는 이유?

개발을 하다보면 OutofMemoryErrors 오류가 발생하는 상황이 생긴다.
프로그램이나 애플리케이션에서 사용 가능한 양보다 많은 메모리를 사용하기 때문에 생기는 오류이다.

오류를 해결하기 위해서는 메모리 양을 늘리거나, 메모리 사용량을 최적화하는 방법이 있다.
최적화를 하기 위해서는 가비지 컬렉션을 활용한다.

한정된 메모리를 효율적으로 사용할 수 있고, 개발자 입장에서도 메모리 관리, 누수, 문제에 대해 완벽하게 관리하지 않아도 되어 개발적인 효율이 올라간다.

가비지 컬렉션과 가비지 컬렉터

주제를 정할 때 가비지 컬렉션에 대해 알아보자고 했는데, 공부를 해보니 가비지 컬렉션도 있고 가비지 컬렉터도 있는 것을 알게 되었다.

  • 가비지 컬렉션: 메모리 관리를 담당하는 시스템 또는 프로그램의 구성 요소. 메모리에서 더이상 사용되지 않는 객체를 찾아서 제거하여 메모리를 회수하는 역할
  • 가비지 컬렉터: 메모리 관리 기술 중 하나. 가비지 컬렉션에 의해 수행되는 프로세스

가비지 컬렉션은 실제로 메모리를 관리하는 프로세스 자체이고, 가비지 컬렉터는 그 프로세스를 수행하는 주체

heap 영역

heap 영역은 가비지 컬렉션의 대상이 되는 곳이다.

크게 구분을 하면 아래 세 가지로 나뉜다.

  • Young Generation (Young 영역)
    새롭게 생성된 객체가 할당되는 영역
    대부분의 객체가 금방 생성되었다가 금방 사라진다.
    (추후에 얘기하겠지만 금방 Unreachable 상태가 되어 가비지 컬렉션의 대상이 되어 사라지는 것)
    Minor GC가 수행된다.
  • Tenured Generation (Old 영역)
    Young Generation에서 오래 할당되어 살아남은 객체가 복사되는 영역
    Young Generation보다 큰 객체들이 할당되며, 영역의 크기가 큰만큼 가비지(더 이상 사용되지 않는 객체)는 적다.
    Major GC가 수행된다.
  • Permanent Generation

가비지 컬렉션의 작동 원리


1. Stop the world

우선 JVM에서 가비지 컬렉션을 실행하기 위해 어플리케이션의 실행을 멈춘다. 이를 Stop the World라고 한다.
GC가 실행되면 GC를 사용하는 스레드를 제외하고는 모든 스레드들의 작업이 중단되고, GC의 작업이 끝나면 그때 작업이 재개된다.

굳이 이것을 왜 하냐, 참조된 객체와 아닌 객체를 구분을 해야 하는데 프로그램 실행 중에도 추적이 물론 가능하다.
하지만 매우 느리기 때문에 일시적으로 스레드를 멈춰놓고 추적 작업을 하는 것이다.

2. 가비지 컬렉션 알고리즘 수행

가비지 컬렉션 알고리즘은 다양하다. 일반적으로 사용되는 것에는 아래와 같은 것들이 있다.

  1. Mark-and-Sweep
    Young 영역에서 사용하는 알고리즘
  2. Mark-Sweep-Compact
    힙의 Old 영역에는 큰 객체들이 저장되는데 Mark-and-Sweep 알고리즘을 사용하면 많은 시간과 메모리가 소모된다.
    그래서 Old 영역에는 이 알고리즘을 사용한다.

이외에도 다른 알고리즘이 있지만, 우리는 이 두 개에 대해 알아보자.

자바에서 모든 객체는 메모리의 일부인 힙에 저장이 된다. 이 객체가 프로그램의 어느 부분에서도 참조되지 않는다면 가비지 컬렉션의 대상이 되게 된다.
가비지 컬렉터는 주기적으로 힙 메모리를 스캔하고, 사용되지 않는 객체를 찾는다. 이 과정을 Mark and Sweep (and Compact)이라고 한다.

  1. 표시(Mark)
    프로그램에서 참조를 하고 있는 모든 객체를 참조 중이라고 표시하는 작업이다.
    루트에서 추적할 수 있는 모든 객체에 표시를 한다. 표시 되지 않은 객체 즉, 루트에서 접근할 수 없는 객체의 경우 가비지 컬렉션의 대상이 된다.

    이때 가비지 컬렉션은 객체가 가비지(더이상 사용되지 않는 객체)인지 판별하기 위해 Reachablity라는 개념을 사용한다.
    참조를 하고 있으면 Reachable, 참조가 없으면 Unreachable로 구별한다.
    가비지 컬렉션은 Unreachable을 대상으로 하는 것

  2. 청소(Sweep)
    표시가 다 끝난 후, 가비지 컬렉터가 힙을 청소하면서 표시되지 않은 객체에서 사용하는 메모리를 식별하고 회수한다.
    또, 표시되지 않은 객체에서 사용하는 메모리를 할당 해제하고 이 메모리 공간을 다시 사용 가능하다는 것을 알리기 위해 메모리 풀에 추가를 한다.

  3. 압축(Compact)
    일부 가비지 컬렉션 알고리즘에서는 청소 후 압축 단계를 실행한다.
    이 단계에서는 나머지 객체에서 사용하는 메모리를 재배열하여 조각화를 최소화한다. 객체를 서로 가깝게 이동시키고 더 큰 연속 메모리 블록을 만드는 작업이 수행된다.

    조각화
    메모리 공간이 여러 작은 조각들로 분산되어서 연속된 큰 메모리들을 넣기 위한 블록이 부족해지는 현상
    조각화가 발생하면 큰 객체를 생성할 때 필요한 연속된 메모리 공간 확보가 어려워지고, 메모리 효율이 떨 어지게 된다.
    Old Generation에 큰 객체들을 할당하기 위해 조각화를 해결하는 압축을 해야한다.

Mark-Sweep-Compact

이 사진을 보면 위 두 개의 알고리즘을 쉽게 이해 가능하다.

  1. Unreachable 구별하기
  2. Unreachable 메모리 회수하고, 메모리 풀에 메모리 공간 사용 가능하다고 추가하기
    (Mark-Sweep은 여기까지만 실행)
  3. 조그만 조각들로 나뉘어진 메모리를 재배열하여 큰 메모리로 만들기

0개의 댓글