GC(Garbage Collection)
시작하며
Java에서는 new를 통해서 객체를 생성하게 된다. 자바 파일이 compile 되면 os가 JVM에게 할당한 메모리 중 JVM의 Run time data area의 Heap 영역에 new를 통해서 만든 객체가 메모리에 할당하게 된다. 이렇게 할당된 메모리는 언젠가는 반환 되어야 하는데 C에서는 delete라는 연산자를 통해서 반환 시키지만 Java에서는 delete를 사용한 적이 없다. 이유가 왜일까? 바로 GC(Garbage Collection)를 통해서 자동으로 메모리를 반환 하기 때문이다. 이번 시간에는 이런 GC가 어떻게 동작하는지 그리고 GC의 알고리즘에는 어떠한 것들이 있는지 살펴보자
JVM Heap Area구조
실제로 heap Area를 보면 크게 4가지 구역으로 나눌 수 있다.
- Eden
자바 객체가 생성되자 마자 저장되는 곳이다.
Minor GC를 통해 Survival 영역으로 이동한다. - Survival0, Survival1
Eden에서 Minor GC를 통해 살아남은 객체가 저장 되는 곳이다.
객체는 Survival0 또는 Survival1 둘 중 하나에만 존재 해야한다. - Old Generation
- GC를 진행할 때마다 Object aging이 발생하여 age 값이 1씩 증가하는데 특정 임계값이 되면 Old Generation으로 Object가 이동한다.
- Survial의 메모리가 꽉 차게 될 때도 Old Generation 이동하게 된다
Young Generation에서 Old Generation으로 이동하는 경우 Promotion이라고 한다. 그리고 Old 영역에서 발생하는 GC를 Major GC(Full GC)라고 부른다.
GC 동작방식
앞서 Heap 영역 구조를 설명했다. 실제로 하나의 객체가 생성되면 Eden에 생성이 됐다가 GC가 진행 될 때 마다 S1 -> S2 -> S1..... 갔다가 끝까지 메모리가 반환 되지 않으면 Old 영역으로 가게 된다. 그렇다면 GC의해서 메모리에 남아있고 반환 되는 기준이 무엇인가?
GC Root 즉 참조할 수 있는 처음 Object를 기준으로 참조를 하고 있으면 GC에서 살아남아 메모리에 남아 있고 참조하지 않으면 메모리를 반환 하게 된다.
Mark and Sweep 알고리즘
Mark and Sweep은 GC에서 사용하는 기본적인 알고리즘인다.
Mark
JVM이 현재 사용되고 있는(즉, 여전히 참조되고 있는) 객체를 식별합니다.
Sweep
Mark 단계에서 마크되지 않은 객체들을 메모리에서 해제합니다.
Compaction
Mark and Sweep 알고리즘 자체에는 Compact 단계가 포함되지 않지만, 일부 GC 구현에서는 메모리 단편화 문제를 해결하기 위해 Compact 단계를 추가합니다.
Stop the World
가비지 컬렉션(GC)이나 기타 중요한 작업을 수행하기 위해 모든 애플리케이션 스레드를 일시적으로 멈추는 과정을 의미합니다. 이 과정 동안 JVM은 메모리 관리나 기타 중요한 작업을 안정적으로 수행할 수 있습니다.
실제적으로 Mark 단계에서 메모리를 참조 하는지 안하는지 봐야 하는데 이때 STW를 안하면 일관되지 않으므로 STW가 작동하게 된다.
결국 개발자는 GC를 통해 메모리 누수를 없애야 하며 STW시간을 줄여야한다.