가비지 컬렉션(Garbage Collection)
728x90

Garbage Collection?

가비지컬렉션은 JVM의 Heap 영역에서 동적으로 할당했던 메모리 중에서 필요 없게 된 메모리 객체들을 모아서 주기적으로 제거하는 프로세스를 말한다.

 

JVM은 프로그램 실행 시 메모리를 여러 영역으로 나누어 관리한다. 각 영역의 역할은 다음과 같다.

Heap: 동적으로 생성된 객체와 배열이 저장되고, 가비지 컬렉션의 주요 대상이다.
Stack: 메서드 호출 시 생성되는 지역 변수, 메서드 호출 정보를 저장한다.
Method Area (or MetaSpace): 클래스, 메서드 정보와 같은 메타데이터를 저장한다.
PC Register, Native Method Stack: JVM이 사용하는 다른 정보 저장 영역.

 

가비지 컬렉션의 역할과 필요성

  • 역할: 더 이상 참조되지 않는 객체를 메모리에서 해제하여 메모리 누수를 방지하고, 새로운 객체를 저장할 공간을 확보한다.
  • 필요성: 개발자가 직접 메모리를 관리할 필요를 줄이고 안정성을 높인다. (예: C의 malloc과 달리 메모리 해제를 명시적으로 호출하지 않아도 됨.)

 

가비지 컬렉션의 장단점

  • 장점 : 가비지 컬렉션(GC)이 한번쓰이고 버려지는 객체들을 주기적으로 비워줌으로써 한정된 메모리를 효율적으로 사용할 수 있게한다.
  • 단점 : 메모리가 언제 해제되는지 정확하게 알 수 없어서 제어하기 힘들다. 가비지 컬렉션이 동작하는 동안 다른 동작을 멈추기 때문에 오버헤드가 발생되는 문제점이 있다.

 

단점에서 발생하는 문제를 "Stop-The-World" 라고 말한다.

Stop-The-World ? 
JVM(Java Virtual Machine)이 Garbage Collection(GC)을 수행하기 위해 애플리케이션의 모든 실행 중인 스레드를 일시적으로 멈추는 현상을 의미
Garbage Collection은 JVM의 메모리를 정리하는 작업이다. GC가 실행되는 동안에는 애플리케이션의 상태가 변경되면 안 되기 때문에, JVM은 모든 애플리케이션 스레드를 일시 중지하고 GC 작업을 완료한 뒤에 스레드를 다시 실행한다.
이 시간을 최소화 시키는 것이 중요하다.

 

GC가 자주 실행되면 STW 시간이 길어지기 때문에 소프트웨어 성능 하락 이슈가 발생한다. 예로, 익스플로러가 GC를 너무 자주 실행해서 성능 문제를 일으키는 이슈가 있었다.

실시간 동작이 중요한 프로그램일 경우에는 GC를 효율적으로 실행하여 애플리케이션의 사용성을 떨어뜨리면 안되는 것이 중요하다.

이렇게 GC를 효율적으로 실행하는 작업을 GC 튜닝이라고 한다.

 

가비지 컬렉션 대상은?

위에서 잠깐 언급한 것처럼 가비지 컬렉션은 Heap 영역의 동적으로 할당된 메모리 중에서 필요없게 된 메모리들을 주기적으로 정리하는 프로세스를 진행한다.

이때, 필요없게 된 메모리를 어떻게 판단할까?

GC는 특정 객체가 Garbage인지 아닌지 알기 위해 "Reachability"라는 개념을 적용한다.

객체의 reference가 있다면 Reachable, 객체에 유효한 레퍼런스가 없다면 Unreachable로 구분한다.

이때 Unreachable인 객체들이 GC의 대상이 된다.

JVM 메모리에서는 객체들은 실질적으로 Heap영역에서 생성되고 Method Area이나 Stack Area 에서는 Heap Area에 생성된 객체의 주소만 참조하는 형식으로 구성된다. 이렇게 생성된 Heap Area의 객체들이 메서드가 끝나는 등의 특정 이벤트들로 인하여 Heap Area 객체의 메모리 주소를 가지고 있는 참조 변수가 삭제되는 현상이 발생하면, 위의 그림에서의 빨간색 객체와 같이 Heap영역에서 어디서든 참조하고 있지 않은 객체(Unreachable)들이 발생하게 된다.

Heap영역은 처음 설계될 때 다음의 2가지를 전제 (Weak Generational Hypothesis)로 설계되었다.

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

-> 객체는 대부분 일회성되며, 메모리에 오랫동안 남아있는 경우는 드물다.

 

JVM 개발자들은 효율적인 메모리 관리를 위해 객체의 생존 기간에 따라 물리적인 Heap 영역을 나누었다.

  • Young Generation : 새로운 객체들이 할당되는 영역 
    • Young 영역에 대한 가비지 컬렉션(Garbage Collection)을 Minor GC라고 부른다.
    • Eden, survivor 0, survivor 1로 나뉜다.
Eden ?
new를 통해 새로 생성된 객체가 위치. 
정기적인 쓰레기 수집 후 살아남은 객체들은 Survivor 영역으로 보낸다.

Survivor 0 / Survivor 1 ?
최소 1번의 GC 이상 살아남은 객체가 존재하는 영역
Survivor 영역에는 특별한 규칙이 있는데, Survivor 0 또는 Survivor 1 둘 중 하나에는 꼭 비어 있어야 하는 것이다.
  • Old Generation : Young Generation에서 오랫동안 살아남은 객체들이 존재하는 영역
    • Young Generation에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역
    • Young Generation보다 크게 할당 되었고, GC는 그만큼 적게 일어난다. 
    • Old 영역에 대한 가비지 컬렉션(Garbage Collection)을 Major GC or Full GC라고 부른다.

 

 

가비지 컬렉션은 어떻게 Garbage를 처리할까?

(1) Mark-and-Sweep

  • Mark 단계:  Root Space 로 부터 그래프 순회를 통해 모든 객체를 탐색하며, reachable한 객체에 "마크" 표시를 합니다.
  • Sweep 단계: 마크되지 않은 객체를 메모리에서 제거합니다.

  + Mark-and-Compact : 객체가 제거되어 파편화된 메모리 영역을 앞에서부터 채워나가는 작업(Compaction)을 수행

 

[ GC의 Root Space ?]
Mark And Sweep 방식은 루트로 부터 해당 객체에 접근이 가능한지가 해제의 기준이 된다.
- JVM GC에서의 Root Space는 Heap 메모리 영역을 참조하는 method area, static 변수, stack, native method stack을 말한다.

 

(2) Copying

  • 사용 방법: 주로 Young Generation에서 사용됩니다.
  • 과정
    1. 도달 가능한 객체를 새로운 메모리 영역(Space)으로 복사합니다.
    2. 기존 메모리 영역의 모든 객체를 제거합니다.
  • 장점: 메모리 조각화가 발생하지 않습니다.
  • 단점: 복사 작업의 추가 비용이 발생합니다.

 

(3) Generational Garbage Collection

JVM의 메모리를 Young GenerationOld Generation으로 나누어 관리하는 방식

    • Young Generation:
      • 새롭게 생성된 객체를 저장한다.
      • 대부분의 객체는 짧은 생명주기를 가지므로 Young Generation에서 빠르게 수집된다.
    • Old Generation:
      • Young Generation에서 생존한 객체를 저장한다.
      • 오래된 객체가 적은 빈도로 수집된다.

위에서 대상에 대해 이야기 할 때 더 자세히 작성해두었다.

 

(4) G1 Garbage Collector

  • 메모리를 여러 Region으로 나누어, Garbage가 많은 영역부터 우선 수집한다.
  • Stop-the-World 시간을 줄이고 성능을 최적화한 방식이다.

 

 

참고: https://inpa.tistory.com/entry/JAVA-☕-가비지-컬렉션GC-동작-원리-알고리즘-💯-총정리#가비지_컬렉션_대상 [Inpa Dev 👨‍💻:티스토리]

 

728x90
반응형