혹시 인사이드에서 이 장면 아는 분 있으신가요? 많은 분들을 울렸던 장면이죠..
한때는 라일리가 가장 좋아했던 상상속 친구 "빙봉"이죠.
빙봉은 라일리가 커갈수록 잊혀지게 되고, 결국 기억의 매립지로 사라지게 되죠.
영화에서 기억을 정리하는 것처럼 Java에서는 JVM
이 메모리를 관리하고 더 이상 사용되지 않는 객체들을 삭제하는 역할을 합니다.
부끄럽지만, 지금까지 Java로 개발을 하면서 메모리가 어떻게 관리되는지 잘 알 지 못했습니다. 그럼에도 아무 문제 없이 개발했던 건 C나 C++과는 다르게, 메모리를 관리해주는 JVM이 있었기 때문입니다. 이제는 알아두면 좋을 주제같아서 공부를 하게 되었습니다.
JVM의 동적으로 할당되는 메모리 영역 Heap 에서 필요 없게 된 메모리를 주기적으로 삭제하는 프로세스를 말합니다.
GC 알고리즘
1. Serial GC
2. Parallel GC
3. Parallel Old GC
4. CMS(Concurrent Mark Sweep) GC
5. G1(Garbage First) GC
세부적인 동작 방식은 다르지만, GC를 수행할 때 기본적으로 2가지 단계를 따른다고 합니다.
- Stop-The-World
- Mark and Sweep
Stop-The-World 단계에서 다른 쓰레드들을 모두 중지시키면, Mark and Sweep 과정이 일어나는 것입니다.
Root 객체에서부터 시작하여 참조되고 있는 객체와 그렇지 않은 객체를 구분합니다.
여기서 Root 객체가 될 수 있는 것은 다음과 같습니다.
- 실행중인 쓰레드 (Active Thread)
- 정적 변수 (Static Variable)
- 로컬 변수 (Local Variable)
참조되고 있는 것과 아닌 것에 대해 조금 더 자세히 살펴보겠습니다.
위와 같이 객체들을 실질적으로 Heap 영역에서 생성되고 Method Areask Stack Area 등 Root Area에서는 생성된 객체의 주소만 참조하는데요.
메서드 종료와 같은 이벤트 후에 객체를 참조하고 있는 변수가 사라진다면, 해당 객체는 참조되고 있지 않은 상태이므로 더 이상 사용할 일이 없습니다. 따라서 GC의 대상이 됩니다. 이러한 객체를 "Unreachable"하다고 표현하기도 합니다.
Reachable: 객체가 참조되고 있는 상태
Unreachable: 객체가 참조되고 있지 않은 상태
주로 Sweep이라고 하는데, Delete라고 표현하는 영상이나 글도 있어서 헷갈렸습니다.
제가 이해하기에는 "메모리를 휩쓴다."는 의미에서 Sweep을 사용하기도 하고, "참조되지 않는 객체를 삭제한다"는 의미에서 Delete라고도 하는 것 같습니다. 주로 Mark and Sweep이라고 붙여서 많이 사용되는 것 같습니다.
참조되고 있지 않다고 Mark한 객체를 삭제하는 과정입니다.
말 그대로 압축단계인데, 남아있는 객체들을 쭉 모아서 압축시킵니다. 그렇게 되면, 새로운 객체가 생성되어 메모리를 할당해야할 때, 조금 더 쉽고 빠르게 진행이 가능하다고 합니다. 성능향상을 위해 수행된다고 하는데, JVM 종류에 따라서 실행여부가 다른 것 같습니다. 하지 않는 경우도 있다고 하네요.
자세한 건 아래 GC 동작 과정에서 살펴보시면 좋을 것 같습니다.
동작을 조금 더 쉽게 이해하고자 애니메이션을 만들어봤습니다.
새로운 객체가 생성되면, Eden
영역에 할당되게 됩니다. Eden
영역이 다 채워지게 되면, Minor GC가 일어납니다.
Marking → Deleting → Copying 이렇게 순서대로 GC가 수행됩니다.
Deleting 후 살아남은 객체는 Survivor 중 한 공간으로 이동합니다.
새로운 객체들로 인해 Eden 공간이 채워지게 되면, 또 다시 Minor GC가 일어나는데요. 이 때 주의깊게 볼 것은 Copying 과정입니다. 살아남은 객체를 옮길 때에는 두 개의 Survivor 공간 중 이미 채워져있는 공간으로 이동시킵니다.
위 에니메이션에서 보면 Copying을 다 끝내기 전에 Survivor0
공간이 가득차게 됩니다. 그래서 세 번째 GC가 수행됩니다.
Survivor0
에서 살아남은 객체들은 Survivor1
으로 이동하게 됩니다. 아까 이동하지 못했던 Eden의 객체들도 이동합니다.
눈썰미 좋은 분들은 눈치채셨을 것 같은데요. 객체에 쓰여져있는
나이
에 주목해주세요. GC 과정에서 살아남을 때마다 1씩 증가합니다.
계속해서 Filling → Marking → Deleting → Copying 과정이 반복적으로 수행됩니다.
그럼 이쯤에서 Old Generation
은 언제 사용되는 건지 Major GC
는 언제 일어나는건지 궁금하실 것 같아요.
6번째 Minor GC를 보면서 설명드리겠습니다.
위에서 잠시 언급한 것처럼 GC에 살아남을 때마다 객체의 나이가 1씩 증가하는데요. 특정 나이를 넘게 되면, Old Generation으로 이동합니다.
(이 예시에서는 설명을 위해 기준을 좀 낮게 3으로 설정했습니다.)
지금까지 Minor GC에 대한 수행과정을 살펴봤는데요. Minor GC에서 살아남은 객체들이 Old Generation으로 이동하게 되면, 언젠가 Old Generation도 꽉 차게 되겠죠. 그 때 Major GC가 일어납니다.
이렇게 예시의 모든 단계를 살펴봤는데요. GC를 이해하는데 도움이 되었으면 좋겠네요.
이 부분에 대한 정보는 많지 않아서 이 정도로 찾아봤습니다. 여기서도 GC가 일어나는지는 잘 모르겠어서 궁금하네요.
여기까지 읽어주신 분이 있다면 감사합니다😃 잘못된 정보를 댓글로 피드백해주시면 빠르게 수정하도록 하겠습니다.