JVM (Java Virtual Machine)이 운영체제의 메모리에 접근하여 메모리를 관리하는데 동적으로 할당한 메모리 영역 중 사용하지 않는 메모리 영역을 자동으로 해제시켜 관리해주는 것을 말한다.
가비지 컬렉션은 C언어와 같이 개발자가 메모리를 해제하지 않고 JVM이 자동으로 메모리를 관리하기 때문에 “해제된 메모리 참조", “자동으로 메모리 해제” 등의 장점이 있다.
반대로, 가비지 컬렉션은 코드레벨에서 발생하는 것이 아니기 때문에 오버헤드가 발생하며, JVM이 가비지 컬렉션을 자동으로 진행하기 때문에 개발자는 어느 시점에 가비지 컬렉션이 실행되는지 모른다는 단점이 있다.
JVM의 가비지 컬렉션의 동작을 확인하기 전에 간단하게 JVM의 Runtime Area 구조에 대해 확인이 필요하다.
JVM의 가비지 컬렉션은 Method Area, Stack Area, Native Method Stack으로 이뤄진 Root Space에서부터 시작해 Heap Area에 도달한 객체들을 찾는다.
public Class Test {
public static void main(String[] args) {
int num = 1; // Stack Area 저장
String name = "Zayson" // name 객체변수는 Stack, Zayson이라는 객체값은 Heap에 저장
List<String> list = new ArrayList<>(); // list 객체변수는 Stack, new로 생성된 객체는 Heap에 저장
}
}
이렇게 Root Space 부터 Heap Area에 도달해 객체를 찾는 것을 “Mark” 한다고 한다.
그리고 도달하지 못해 어떤 Root Space에서도 도달되지 않고 참조되지 않는 객체들을 Unreachable Object라고 하고 이는 가비지 컬렉션의 대상이된다. 이를 “Sweep” 한다고 한다.
이렇게 남은 객체들을 정리하기도 하는데 이를 “Compaction(압축)” 한다고 하며, 이는 메모리 단편화를 방지해주는 역할을 하며 필수적으로 실행되지는 않는다.
가비지 컬렉션은 JVM이 원할때 의도적으로 실행되어야 한다. 따라서, JVM은 Heap Area 내에서도 어떠한 기준을 통해서 가비지 컬렉션을 실행한다.
Heap Area를 조금 더 구체적으로 파헤쳐보면 “Eden”, “Survival 0”, “Survival 1”로 구성된 “Young Generation” 영역과 “Old Generation” 영역으로 구성된다.
Eden 영역은 새롭게 생성된 객체가 저장되는 영역으로 새롭게 객체가 생성되면 아래와 같이 메모리를 차지한다. 아래 객체의 숫자는 Age Bit를 나타낸다.
그렇게 Eden 영역이 가득 차게 된다면 JVM은 “Minor GC”를 진행한다.
Minor GC는 Eden 영역에서 사용하는 객체들을 마킹한 후, 비어있는 Survival 영역으로 이동시켜 준 후 Age Bit를 1 증가 시킨다.
Young Generation의 Survival 0과 Survival 1 영역 중 한 영역은 반드시 비어있다.
이후 , 다시 Eden 영역이 가득차게 되면 JVM은 다시 Minor GC를 진행한다. JVM은 Eden 영역과 Survival 0 영역에서 사용하는 참조하는 객체들을 마킹한 후, 비어있는 Survival 1 영역으로 이동시키고 Age Bit를 1 증가 시킨다.
이러한 동작이 반복되면서, Age Bit가 특정 기준에 도달하면, JVM은 해당 객체들을 오랫동안 참조해야할 객체로 인식한 후 Old Generation 영역으로 이동시킨다. 이렇게 이동시키는 것을 “Promotion” 한다고 한다.
다시 동작이 반복되면서, Old Generation 영역이 가득차게 되면 JVM은 Old Generation 영역에서 참조하는 객체들을 마킹한 후 Unreachable Object들을 Sweep 하는데 이를 “Major GC”라고 한다. Major GC는 Minor GC 보다 시간이 오래걸리며, 리소스도 많이 사용한다.
Stop-The-World (STW) : 가비지 컬렉션을 실행하기 위해 JVM이 애플리케이션 실행을 멈추는 것을 말한다.
조엘의 GC : https://youtu.be/FMUpVA0Vvjw
던의 JVM의 Garbage Collector : https://youtu.be/vZRmCbl871I