Java

[Java] JVM GC 처리 과정

체리1001 2024. 4. 16.

1. GC란

Garbage Collection의 약자인 GC는 JVM에서 제공하는 메모리 관리 기능입니다.

Runtime Data Area의 Heap 영역에 저장된 객체들을 따로 정리하지 않으면, 메모리가 가득차 에러가 발생할 수 있습니다. 이를 방지하고자 JVM에서는 GC를 통해 메모리를 관리해 주며, 이 덕분에 개발자는 편하게 프로그래밍을 할 수 있습니다!

(개발자들은 어느 시점에 GC가 동작하는지 모릅니다. 언제 역할을 수행하는지는 모르지만.. 늘 고마워 GC..)

 

Java에서 System.gc()를 직접 호출할 수도 있지만.. 해당 메소드를 호출하는 것은 시스템의 성능에 매우 큰 영향을 미치므로 절대 호출해서는 안됩니다!

 

2. Java에 GC 도입이 가능했던 이유

Java는 weak generational hypothesis 로 인해 GC 도입이 가능했습니다.

weak generational hypothesis 는 약한 세대 가설로, 아래 두 가지 내용을 뜻합니다.

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

즉, 객체는 대부분 일회성이며 메모리에 오랫동안 남아있는 경우가 드물다는 것입니다! 이러한 가설을 바탕으로 객체의 생존 기간이라는 기준이 만들어진 것이죠!

 

3. JVM 메모리 구조

앞서 언급했듯이 JVM은 효율적인 메모리 관리를 위해 객체 생존 기간에 따라 물리적으로 Heap 영역을 나누었습니다.

 

(1) Young Generation

Young 영역에는 Eden, Survivor1, Survivor2가 포함되어 있습니다.

  • Eden: new 키워드를 통해 생성된 객체가 저장됩니다. 정기적인 쓰레기 수집 후 살아남은 객체들을 Survivor로 보내집니다.
  • Survivor1 & Survivor2: 최소 1번 이상의 GC를 살아남은 객체가 존재하는 곳입니다. (Survivor1과 Survivor2 중 하나는 반드시 비어있는 상태여야 합니다.)

(2) Old Generation

Old 영역은 Young 영역에서 접근 가능(reachable) 상태를 유지하여 살아남은 객체가 복사되는 영역입니다.

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

(3) Permanent Generation

Permanent 영역은 Java 7 버전까지는 Heap Area에 함께 존재했으나, Java 8 버전부터는 Native Method Stack에 포함되었습니다.

 

4. GC 동작 과정

GC가 동작을 하면 Stop the world, Mark and Sweep 이렇게 두 가지 동작을 수행합니다.

(1) Stop the World

JVM이 GC를 실행하기 위해 애플리케이션의 실행을 멈추는 작업으로, GC 작업을 수행하는 스레드를 제외한 모든 스레드의 작업이 중단됩니다. (애플리케이션이 중단된다고? 그럼 어떡해? -> 애플리케이션 중단 시간 최소화를 위해 Stop the world 작업의 소요 시간을 줄이기 위한 다양한 알고리즘이 존재합니다)

(2) Mark and Sweep

GC는 객체를 판별할 때는 reachability 개념을 활용합니다. 힙 영역에 있는 객체에 대한 유효 참조가 있다면 reachable이며, 없다면 unreachable로 GC로 인한 소멸 대상이 됩니다.

 

Stop the World 작업 이후 스택의 모든 변수 또는 접근 가능한(reachable) 객체를 스캔합니다.

  • 1. (Mark 과정) GC가 스택의 모든 변수를 스캔하면서 어떤 객체를 참조하고 있는지 찾아서 마킹을 한다.
  • 2. (Sweep 과정) 마킹되지 않은 객체를 Heap에서 제거한다. (Sweep 과정)
  • (3. compact를 하는 GC라면 단편화된 메모리를 정리한다.)

 

5. Minor GC

Minor GC는 Young 영역에 대한 GC입니다.

새로 생성된 객체는 대부분 Eden 영역에 위치하며, Eden 영역에서 GC가 한 번 발생한 뒤에 살아남은 객체는 Survivor 영역으로 이동합니다. 이 과정을 반복할 때 오래 살아남은 객체는 일정 시간 참조되고 있다는 뜻이므로 Old 영역으로 이동하게 됩니다.

(1) 오래 살아남았다는 것의 기준은?

Young 영역에서 오래 살아남은 객체는 Old 영역으로 이동합니다. 이때, 오래 살아남았다는 것의 기준은 어떻게 될까요?

 

기준은 말 그대로 Minor GC를 얼마나 많이 견뎠냐를 의미합니다. 각 객체는 Minor GC에서 살아남은 횟수를 기록하는 age bit를 가지고 있으며, Minor GC가 발생할 때마다 1씩 증가합니다. age bit가 MaxTenuringThreshold 라는 설정값을 초과할 때 Old 영역으로 이동하게 되며, 이 외에도 Survivor 영역의 메모리가 부족할 경우에는 미리 Old 영역으로 객체가 옮겨질 수도 있습니다.

 

6. Major GC (=Full GC)

Major GC는 Old 영역에 대한 GC입니다.

Old 영역의 객체들을 검사하여 참조되지 않은 객체들을 한번에 삭제합니다.

 

 

참고
https://mirinae312.github.io/develop/2018/06/04/jvm_gc.html  https://velog.io/@mooh2jj/JVM-GC%EC%9D%98-%EC%B2%98%EB%A6%AC-%EA%B3%BC%EC%A0%95

'Java' 카테고리의 다른 글

[Java] static 알아보기  (0) 2024.04.22
[Java] 래퍼 클래스(Wrapper Class)란  (0) 2024.04.18
[Java] JVM의 구조와 자바 컴파일 과정  (0) 2024.04.16
[Java] Call by Value vs Call by Reference  (0) 2024.04.16

댓글