며칠 전, Go개발자와 이야기를 나누다 Go의 Garbage Collection이 흥미롭다며 이야기를 꺼냈다.
Go의 Garbage Collection은 사용하지 않는 메모리(가비지)를 Garbage Collector를 통해 삭제한 후 해당 메모리 만큼을 가비지를 수집해야 그다음번 Garbage Collection이 작동된다고 한다. 그렇기 때문에 점점 느려져, c언어처럼 mmap계열을 사용해 커널의 메모리 API를 사용하는 등으로 메모리 오버헤드를 제거한다고 한다. PintOS 생각난다며 신나있던 그의 모습을 잊을 수가 없다.. 천생 개발자..
Go를 사용해보지 않아서 잘 모르지만, 'Java는? Java의 Garbage Collection은 어떻게 동작할까?' 하는 호기심이 생겼다.
자바의 메모리 관리 방법 중 하나로 JVM의 Heap 영역에서 동적으로 할당했던 메모리 영역 중 필요 없게 된 메모리 영역을 주기적으로 삭제하는 프로세스를 말한다.
PintOS 당시 C에서는 이러한 가비지 컬렉션이 없어 수동으로 메모리 할당과 해제를 일일이 해줘야 했지만, Java는 JVM에 탑재된 가비지 컬렉터가 메모리 관리를 대행해줘서 개발자 입장에서는 메모리 관리, 메모리 누수 문제에 대해 완벽히 관리하지 않고 오롯이 개발에만 집중할 수 있다는 장점이 있다.
red-black tree를 C언어로 구현할 때도 할당한 메모리를 해제해주지 않는다면, test case를 돌렸을 때 누수된 메모리가 상당했고, 예기치 못하게 종료됬던 것이 기억에 남는다.
반면, 가비지 컬렉션도 단점이 존재하는데
1. 개발자가 메모리가 언제 해제되는지 정확히 알 수 없다.
2. 가비지 컬랙션이 동작하는 동안에 다른 동작을 멈추기 때문에 오버헤드가 발생한다.
이로 인해 가비지 컬랙터가 너무 자주 실행되면 소프트웨어 성능 하락의 문제가 되기도 한다.
이러한 특성으로 실시간으로 계속 동작해줘야하는 시스템들은 잠깐의 소프트웨어 일시정도로 목표한 결과가 달라질 수 있어 가비지 컬렉션의 사용이 적합하지 않는다.
따라서, 가비지 컬렉션. 줄여서 GC를 수행하기 위해 JVM이 GC 관련 Thread를 제외한 모든 Thread는 멈추는 현상인 Stop The World를 최소화 시키는 것이 우리의 일이다. 어플리케이션의 사용성과 GC의 편리함의 장점은 유지하면서 효율적이게 GC를 실행하는 최적화하는 것!
JVM 메모리는 객체들이 Heap에 생성되고, Method Area나 Stack에서는 그 객체의 주소만 참조하는 형식이다. 객체를 참조하고 있다면 reachable로 구분되고, 그렇지 않다면 unreachable로 구분하고 수거해버린다.
이는 메서드가 끝나는 등의 이벤트로 인해 Heap영역의 객체의 메모리 주소를 가지고 있는 참조 변수가 삭제되면, 위 그림에서 하늘색 객체와 같이 어디서도 참조하고 있지 않은 객체가 발생하게 된다. 이를 쓰레기로 간주하고 가비지 컬렉터가 제거해주는 것이다.
Mark And Sweep
아래는 객체의 수명에 대한 일반적인 분포를 나타낸 그래프이다. 대부분의 객체는 "어린 나이에 죽는다"는 사실에 초점을 맞추면 효율적으로 Heap을 관리할 수 있다.
이러한 특성을 활용해 JVM 개발자들은 보다 효율적 메모리 관리를 위해, 물리적인 Heap영역을 Young과 Old로 나누어 설계하였다.
더 효율적인 GC를 위해 Young 영역을 3가지로 나누면, Eden, survivor 0, survivor 1로 구성된다.
Eden
new를 통해 새로 생성된 객체가 위치한다.
정기적인 쓰레기 수집 후 살아남은 객체들은 survivor 0으로 보낸다.
survivor 0 / survivor 1
최소 1번의 GC 이상 살아남은 객체가 존재하는 영역으로,
둘 중 하나는 꼭 비어있어야 한다.
처음 생성된 객체는 Young 영역 일부인 Eden 영역에 위치하게 된다.
객체가 계속 생성되 Eden 영역이 꽉차면 Minor GC 가 실행된다.
Major GC는 객체들이 계속 늘어나 Old 영역의 메모리가 부족하면 발생한다.
Old 영역은 상대적으로 큰 공간을 가지고 있어, 메모리 상의 객체를 제거하는데 많은 시간이 걸린다. (Young 영역의 10배이상)
여기서 Stop-The-World 문제가 발생한다!
하여 자바 개발자들은 끊임없이 가비지 컬렉션 알고리즘을 발전 시켜왔다.
Serial GC, Parallel GC, Parallel Old GC, CMS GC, G1 GC, Shenandoah GC, ZGC
참고.
HotSpot Virtual Machine Garbage Collection Tuning Guide
Java Garbage Collection
Java ☕ 가비지 컬렉션 동작 원리 & GC 종류 💯 총정리