[JAVA] 가비지 컬렉션(Garbage Collection)

Jay Lee·2023년 3월 28일
0

정의

가비지 컬렉션(Garbage Collection)은 자바의 메모리 관리 방법 중의 하나로 JVM의 Heap 영역에서 사용되지 않고 있는 객체를 식별하고 해당 객체들에 할당된 메모리를 해제하는 프로세스입니다. 일반적으로 C와 같은 프로그래밍 언어에서는 개발자가 객체의 메모리 할당 해제를 수동적으로 수행하여야 했던 반면 Java에서 메모리 할당 해제 프로세스는 Garbage Collector에 의해 자동으로 처리되어 개발자 입장에서 메모리 관리나 Memory Leak 문제를 일부 JVM에 위임하여 비즈니스 로직 개발에만 집중할 수 있다는 장점이 있습니다.

System.gc()를 통해 gc를 실행 시킬 수 있지만, 메서드를 호출하는 것은 시스템의 성능에 매우 큰 영향을 끼치므로 System.gc() 메서드는 절대로 사용하면 안 된다.


가비지 컬렉션의 단점

  1. 메모리 해제 시점을 명확히 알 수 없다.
  2. 가비지 컬렉션(GC) 중 다른 스레드들의 동작은 중지되기 때문에 오버헤드가 발생한다.

가비지 컬렉션의 대상이 되는 객체


JVM 구조적으로 객체가 생성되었을 때, 모든 객체는 Heap Area에 생성되고 Method Area와 Stack Area에서 이를 참조하여 사용하는 방식으로 구성 되어 있습니다. 이 때, 어떤 참조 변수도 참조 하지 않는 객체를 Unreachable이라고 하며 이들은 가비지 컬렉션의 대상이 됩니다.

Java의 Garbage Collector는 Reachability Analysis(도달성 분석)을 사용하여 Unreachable Object를 판단합니다.
Reachability Analysis는 먼저 모든 루트 객체를 식별하고, 이들 루트 객체에서 시작하여 참조 체인(reference chain)을 추적하며 도달 가능한(reachable) 객체를 식별합니다. 이러한 도달 가능한 객체는 메모리에서 해제되지 않고 유지됩니다.

루트 객체에 해당하는 객체들은 다음과 같습니다.

  1. 현재 실행 중인 메소드에서 사용 중인 지역 변수(local variable)
  2. 현재 실행 중인 메소드에 전달된 매개 변수(parameter)
  3. 현재 실행 중인 메소드에서 호출한 다른 메소드의 스택 프레임(stack frame)
  4. 네이티브 메소드의 JNI(Java Native Interface) 참조
  5. JVM(JAVA Virtual Machine)이 로드한 클래스 중, static 필드에서 참조하는 객체

가비지 컬렉션 기본 동작 과정

가비지 컬렉션의 기본 동작 과정은 크게 Stop the World 과정과 Mark and Sweep 과정으로 나누어진다.

Stop the World

GC를 수행하는 하나의 스레드를 제외하고 다른 스레드들의 동작을 중지시킨다.

Mark and Sweep

Mark: Reachability Analysis 과정을 통해 Unreachable Object를 식별합니다.
Sweep: 해당 객체를 제거합니다.


가비지 컬렉션 동작 시점


가비지 컬렉터는 'weak generational hypothesis'라고 하는 두 가지 전제 조건 하에 만들어졌다

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

해당 전제조건을 기반으로 최적의 GC 수행을 위해서 HotSpot VM에서는 크게 2개로 물리적 공간을 나누었다. 둘로 나눈 공간이 Young 영역과 Old 영역이다.

Young 영역 (Old Generation 영역)

새롭게 생성한 객체의 대부분이 여기에 위치한다. 대부분의 객체가 금방 접근 불가능 상태가 되기 때문에 매우 많은 객체가 Young 영역에 생성되었다가 사라진다.

Young 영역은 Eden 영역과 두개의 Survivor 영역으로 이루어져 있다. Eden 영역이 일정 수준만큼 채워지게 되면 Minor GC가 발생하게 된다.

Minor GC와 관련된 자세한 설명은 https://coding-factory.tistory.com/829 를 참조

참고로, HotSpot VM에서는 보다 빠른 메모리 할당을 위해서 두 가지 기술을 사용한다. 하나는 bump-the-pointer라는 기술이며, 다른 하나는 TLABs(Thread-Local Allocation Buffers)라는 기술이다.

bump-the-pointer와 TLABs에 대한 자세한 정보는 https://d2.naver.com/helloworld/1329를 참조

Old 영역 (Old Generation 영역)

접근 불가능 상태로 되지 않아 Young 영역에서 일정 수준이상 살아남은 객체가 여기로 복사된다. 대부분 Young 영역보다 크게 할당하며, 크기가 큰 만큼 Young 영역보다 GC는 적게 발생한다. Old 영역은 기본적으로 데이터가 가득 차면 Major GC를 실행한다.

GC 방식에 따라서 처리 절차가 달라지므로, 어떤 GC 방식이 있는지 살펴보면 이해가 쉬울 것이다.

Permanent Generation 영역 (Method Area)

객체나 억류(intern)된 문자열 정보를 저장하는 곳이다. Java 7 이전의 버전에서 사용되었으며 Java 8부터는 Perm 영역이 Metaspace로 대체되었습니다. 자세한 설명은 JVM 메모리 구조 참조

Reference

https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
https://d2.naver.com/helloworld/1329
https://coding-factory.tistory.com/829

profile
Data Engineer

0개의 댓글