JVM의 구조에 대해서 포스팅하며 Heap 영역에서 동작하는 GC 에 대해서 언급을 하였다.
GC 의 동작방식에 대해서는 간략하게 설명하였지만 보다 자세하게 포스팅 하기 위해서 작성하였다.
1. Stop - The - World
우리가 GC 에 대해서 알아보기 전에 알아야할 중요한 용어로 "stop-the-world" 가 있다.
stop-the-world 란, GC를 실행하기 위해서 JVM이 애플리케이션 실행을 멈추는 것을 말한다.
stop-the-world 가 발생하면 GC 를 실행하는 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 멈추게되며 GC 작업을 완료한 이후에 중단했던 작업을 다시 시작한다.
Java 는 C언어처럼 프로그램 코드로 메모리를 명시적으로 해제하지 않기 때문에 Garbage Collector 가 더이상 필요없는 객체를 찾아 지우는 작업을 한다.
2. Young 영역의 구성
GC를 이해하기 위해서 제일먼저 객체가 생성되는 Young 영역의 구성을 알아보면
1. Eden 영역
2. Suvivor 0, 1영역
총 3개의 영역이 존재한다. 각 영역의 처리 절차는 다음과 같다.
1. 새로 생성한 인스턴스의 경우 대부분 Eden 영역에 위치한다
2. Eden 영역에서 GC가 한번 발생한 후 살아남은 객체는 Survivor 영역중 하나로 이동된다.
3. Eden 영역에서 GC가 발생하면 이미 살아남은 객체가 존재하는 Survivor 영역으로 객체가 계속 쌓이면서 age 값이 증가하게 된다.
4. 하나의 Survivor 영역이 가득차게 되면 그 중 살아남은 객체를 다른 Survivor 영역으로 이동하게 되고, 가득찬 Survivor 영역은 아무 데이터도 없는 상태가 된다.
5. 이 과정을 반복하다가 계속해서 살아남아 있는 객체는 Old 영역으로 이동하게 된다.
3. Old 영역에 대한 GC
Old 영역은 기본적으로 데이터가 가득차면 GC를 실행한다. GC 의 방식에 따라서 처리절차가 달라지는데
JDK 7 을 기준으로 5가지 방식이 존재한다.
- Serial GC
Serial GC 는 운영 서버에서 절대 사용하면 안되는 방식이다. Serial GC 는 CPU 코어가 하나만 있을때 사용하기 위해서 만드는 방식으로 성능이 많이 떨어진다.
Old 영역의 GC 는 mark-sweep-compact 라는 알고리즘을 사용한다.
첫단계로 Old 영역에 살아있는 객체를 식별(Mark)하는 것이다.
그 다음에는 힙(heap)의 앞 부분부터 확인하여 살아있는 것만 남기고 제거한다(Sweep).
마지막으로 각 객체들이 연속되게 쌓이도록 힙의 가장 앞부분부터 채워서 객체가 존재하는 부분과 객체가 없는 부분으로 나눈다(Compaction)
Serial GC 는 적은 메모리와 CPU 코어수가 적을때 적합하다.
- Parallel GC
Parallel GC는 Serial GC와 기본적인 알고리즘은 같다. 하지만 Serial GC는 GC를 처리하는 쓰레드가 하나인 반면,
Parallel GC는 GC를 처리하는 쓰레드가 여러개 이다. 그렇기 때문에 Serial GC 보다 빠르게 객체를 처리할 수 있다.
- Parallel Old GC (Parallel Compacting GC)
Parallel Old GC는 JDK 5 update 6 부터 제공한 GC 방식이다 앞서 설명한 Parallel GC 에서 사용한 알고리즘과 다르게
Mark - Summary - Compaction 단계를 거친다. Summary 단계는 앞서 GC를 수행한 영역에 대해서 별도로 살아있는
객체를 식별한다는 점에서 Mark - Sweep - Compaction 보다 복잡한 단계를 거친다.
- Concurrent Mark & Sweep GC (CMS)
CMS (Concurrent Mark Sweep) GC는 지금까지 설명했던 GC 보다 훨씬더 복잡하다.
초기 Initial Mark 단계는 클래스 로더에서 가장 가까운 객체중 살아있는 객체만 찾는것으로 끝낸다.
따라서 Stop The World 시간이 짧다.
Concurrent Mark 단계는 방금 살아있다고 확인한 객체에서 참조하고 있는 객체들을 따라가면서 확인한다.
이단계의 특징은 다른 쓰레드가 실행중인 상태에서 동시에 진행되는 것이다.
Remark 단계는 Concurrent Mark 단계에서 새로 추가되거나 참조가 끊긴 객체를 확인한다.
마지막으로 Concurrent Sweep 단계에서는 쓰레기를 정리하는 작업을 수행한다. 이작업 또한 다른 쓰레드가 실행중인
상태에서 동시에 진행된다.
CMS 는 stop the world 시간이 매우 짧아 응답속도가 중요한 애플리케이션에 사용된다.
하지만 단점 또한 존재한다.
1. 다른 GC 방식보다 CPU와 메모리를 더많이 사용한다.
2. Compaction 단계를 기본적으로 제공하지 않는다.
조각난 메모리가 많아서 Compaction 단계를 실행하는 경우 stop the world 시간이 길어지기 때문에 Compaction 작업이 얼마나 자주, 오랫동안 수행되는지 확인해야한다.
- G1 (Garbage First) GC
마지막으로 G1 GC 이다. G1 GC를 이해하려면 여태까지 설명했던 GC를 완전히 잊어야한다.
위 그림에서도 보시다시피, G1 GC는 바둑판의 각 영역에 객체를 할당하고 GC를 실행한다.
객체를 할당하는 영역이 꽉 차게되면 다른 영역에 객체를 할당하고 GC를 실행한다.
즉, 지금까지 설명한 Young의 세가지 영역에서 Old 영역으로 이동하는 단계가 사라진 GC 방식이다.
G1 GC 의 가장큰 성능을 가지고 있으며 5가지 GC중 가장 빠르다.
'JAVA' 카테고리의 다른 글
Java BCI (Byte Code Instrument) (0) | 2022.06.26 |
---|---|
Java Reflection API (0) | 2022.06.25 |
Volatile 을 사용한 가시성 보장 (0) | 2022.03.15 |
쓰레드의 지역변수 ThreadLocal (0) | 2022.03.15 |
일급 컬렉션 (First Class Collection) 을 사용하자 (0) | 2022.03.01 |
String , StringBuilder, StringBuffer 속도차이 비교 (0) | 2022.02.09 |