앞선 글에서, GC 는 프로그램이 동적으로 할당했던 메모리 영역 중에서 필요없게 된 영역을 해제 하는 메모리 관리 기법 이라고 하였습니다.
또한 Java에서 GC 는 JVM 의 가비지컬렉터 가 동작한다고 하였는데요,
이번 글에서는 Java GC 에 대해서 조금 더 알아보려고 합니다.
* Heap영역 : 자바에서 객체를 생성하면 Heap 영역에 저장
Minor GC & Major GC
JVM 은 Heap영역을 설계할 때 2가지 전제조건으로 설계 되었습니다.
1. 대부분의 객체가 금방 접근 불가능한 상태가 된다.
2. 오래된 객체에서 새로운 객체로의 참조는 드물게 존재한다.
이는 대부분의 객체가 일회성인 경우가 많고, 메모리에 오래 남아있는 경우가 드물다는 것을 의미합니다.
이에 따라 Young영역 , Old 영역 으로 구분을 하여 설계하였습니다.
Young 영역 : 새로운 객체의 영역
- 새로운 객체는 이곳에 할당되며, 대부분의 객체가 일회성인 만큼 대부분의 객체는 Young 영역에 오래 남아있지 않고 사라집니다.
- Young 영역을 관리하는 GC 를 Minor GC 라고 합니다.
또한, Young 영역의 구조는 아래와 같이 이루어져 있습니다.
- Eden 영역 : 새로 생성된 객체가 할당되는 영역
Eden 영역이 가득찰때마다, MinorGC 실행
- Survivor1 영역 : Eden 영역에서 1번 이상 살아남은 경우 할당되는 영역
- Survivor2 영역 : Survivor1 영역이 가득찬 경우 Survivor1 영역에서 살아남는 객체가 할당되는 영역
Survivor2 영역에서 계속 해서 살아남으면, 해당영역의 객체들은 Old 영역으로 복사
Old 영역 : 오래된 객체의 영역
- 새로운 객체가 Young 영역에서 사라질 때, Minor GC 를 거쳤지만, 해제되지 않고 살아남은 객체들이 이곳으로 복사됩니다.
- Old 영역에서도 언젠가는 사라져야하는데 이러한 Old 영역을 관리하는 GC 를 Major GC 라고 합니다.
- Old 영역은 Young 영역보다 크며, MinorGC 에 비해 MajorGC는 10배 이상의 시간을 필요로 합니다.
- 이는 MajorGC 가 자주 호출된다면, 성능에 영향을 끼칩니다.
- 그에 따라 MajorGC 는 Old 영역의 메모리가 부족해질 때 호출됩니다.
Card Table
위에서 오래된 객체에서 새로운 객체로의 참조는 드물게 존재한다고 하였습니다.
즉, 오래된 객체가 새로운 객체를 참조할 수도 있다. 라는 것을 의미합니다.
그렇다면,
Minor GC 는 Young 영역에서 해제되어야하는 대상을 찾아야할 때, Old 영역도 확인해야 겠네? 라는 결론이 나오게 됩니다.
하지만 문제가 하나 있습니다. Old 영역에 있는 객체가 Young 영역에 있는 객체를 참조하는 경우는 드물게 발생한다 에서
Old 영역중에 0개 or 1개 의 객체만 Young 영역의 객체를 참조할 수 있다는 것입니다.
n 개의 객체를 제거대상인지 식별하기 위하여 m개의 객체를 검사한다면 n*m 번의 검사가 실행됩니다.
이러한 문제를 해결하기 위하여 Card Table 이 등장합니다.
Card Table : Old 영역의 객체가 Young 영역의 객체를 참조하는 경우에 그에 대한 정보를 저장합니다.
- Minor GC 가 동작할때 Young 영역에 있는 객체들은 Old 영역에 있는 객체와의 n*m 번의 검사가 아니라,
Card Table 에 있는 객체를 확인하여 Young 영역의 객체중 GC 의 대상에서 벗어나야 하는 객체를 식별합니다.
기본적인 GC 공통 동작 : Stop The World & Mark And Sweep
MinorGC 와 MajorGC 는 세부적으로 동작방식이 다릅니다.
간단하게 MinorGC 에서는 CardTable 도 사용하는 로직도 필요하다는 것을 예로 들 수 있겠죠?
하지만 기본적으로 GC 가 실행될 때 공통적으로 동작하는 방식이 있습니다.
1. Stop The World
- JVM 의 가비지컬렉터가 GC 를 실행하기 위하여 GC 를 실행하는 쓰레드를 제외한 나머지 쓰레드를 모두 정지시킵니다.
GC 작업이 종료되면, 나머지 쓰레드를 다시 동작합니다.
즉, Stop The World란 JVM 이 GC 를 실행시키기 위하여 다른 쓰레드를 정지&재개하는 동작입니다.
2. Mark And Sweep
- GC 가 동작할 때, 사용되는 메모리와 사용도지 않는 메모리를 식별하는 Mark 작업과 사용도지 않는 메모리가 식별된 경우, 이를 해제하기 위한 Sweep 작업입니다.
요약
자바의 GC 는 MinorGC 와 MajorGC 로 나뉩니다.
MinorGC : Young 영역에 대한 GC, Young 영역의 구조중 Eden영역이 가득차면 실행됨. 실행속도가 빠르다.
MajorGC : Old 영역에 대한 GC, Old 영역이 가득차면 실행됨. 실행속도가 느리다.
* 객체의 잘못된 사용으로 GC 의 대상이 되지 못하여 메모리 누수가 일어나는 경우 Old영역에 할당되는 객체가 늘어나게 되고,
Old영역이 가득찰때마다 MajorGC 가 실행되는데, MajorGC 에서 해제되는 메모리가 적어지는 만큼 Old영역이 가득차는 경우가 빈번해집니다. 따라서 MajorGC 가 자주 호출되게 되고, 이는 곧 성능에 치명적으로 다가옵니다.
그 이후, Old영역이 가득 찾지만, 더이상 MajorGC 의 대상에 속하지 못하여 사용할 수 있는 메모리가 없어진 순간
펑~ 펑~ 펑 .....
메모리누수를 조심합시당 :)
'BackUp (관리중지) > CS 학습' 카테고리의 다른 글
DI (Dependency Injection ) (0) | 2021.04.29 |
---|---|
REST API (0) | 2021.04.28 |
GC ( Garbage Collection ) (0) | 2021.04.28 |
동시성 이슈 (0) | 2021.04.27 |
쓰레드(Thread) / 프로세스(Process) (0) | 2021.04.27 |