charminseok
[JAVA] Garbage Collection 본문
자바의 JVM은 자바파일을 실행시키는 것 뿐만 아니라 garbage collection(GC)이라는 메모리 관리도 해준다. GC는 사용하지 않는 객체를 JVM이 알아서 정리해주기 때문에 메모리 누수를 방지합니다.
stop-the-world
GC에 들어가기 앞서 가장 먼저 알아야할 용어는 stop-the-world이다. stop-the-world는 GC를 실행하기 위해 JVM이 애플리케이션을 멈추는 것입니다. 그렇기 때문에 stop-the-world가 발생하면 GC를 실행하는 쓰레드 외 모든 쓰레드가 멈추게 됩니다.
Garbage Collection을 하는 대상
자바에서 Reference type의 객체를 생성하면 실제 객체는 heap영역에 저장되고 참조 타입 변수는 스택 영역에 실제 객체의 주소를 저장합니다.
String name = "start";
"start" 실제 객체의 주소가 예를들어 100이라고 한다면 스택영역에는 name이라는 객체가 가리키는 주소인 100이 들어가게 됩니다.
이렇게 스택 영역에서 힙 영역으로 참조하는 객체가 있는데
name = "start again";
으로 다시 할당하게 되면 주소 100에는 "start" 객체가 그대로 들어있고 100이 아닌 다른 주소에 "start again"이 생성되어 name은 "start again"을 참조하게 됩니다.
이때 100에 있는 "start" 객체는 스택영역에서 참조하지 않는 일명 Unreachable Object가 됩니다. GC는 이 도달할 수 없는 객체를 지워줍니다.
Reachable Object를 찾는 과정을 Mark, unreachable object를 삭제하는 과정이 Sweep입니다.
이렇게 찾고 삭제를 거쳐 할당된 부분과 할당되지 않은 부분으로 모으는 작업(Compaction)이 실행됩니다.
Heap 영역
Heap 영역은 Young, Old 영역으로 이뤄져 있습니다.
여기서 Young 영역은 다시 Eden, Survivor 영역 2개로 나눠집니다.
------------------------
| Eden | S0 | S1 | Old |
------------------------
Young 영역에서 일어나는 GC는 Minor GC라 부르고, Old 영역에서 일어나는 GC를 Major GC(또는 Full GC)라고 부릅니다.
Young 영역에서 GC
1. 맨 처음 생성된 객체는 Eden영역에 저장됩니다.
2. Eden 영역이 가득 차면 minor GC가 일어나고 살아남은 객체는 Survivor 영역 중 하나로 이동합니다. (이때 무조건 Survivor 영역 중 하나에만 들어가고 다른 Survivor 영역은 빈 상태를 유지합니다.)
3. 1-2가 반복되며 survivor 영역이 가득 차게 되면 GC를 실행하고 살아남은 객체는 다른 survivor영역으로 이동합니다. (이때도 GC가 일어난 survivor 영역은 빈 상태로 바뀝니다.)
4. 1-3이 반복되며 특정 시간 이상 살아남은 객체는 old 영역으로 이동합니다.
Old 영역에서 GC
old 영역도 가득 차게 되면 GC를 실행하는데 여기선 여러가지 방식으로 GC가 일어납니다.
Serial GC, Parallel GC, Concurrent Mark Sweep (CMS) GC, Garbage-First (G1) GC 여러가지가 있습니다.
- Serial GC
이 GC는 Young 영역과 같은 방식(mark, sweep, compact)으로 일어납니다.
- Parallel GC
Serial GC와 동작은 같지만 GC를 실행하는 쓰레드가 여러 개로 더욱 빠르게 처리할 수 있습니다.
- CMS GC
mark, sweep이 일어나지만 이전 방식과는 약간 다르게 처리됩니다. 먼저 Initial Mark 단계로 클래스 로더와 가장 가까운 객체 중 살아있는 객체를 찾습니다. 다음 Concurrent Mark 에서는 객체 참조 간 변경 사항을 확인하고 Final Remark 과정을 통해 살아있는 객체를 마킹합니다. 마지막으로 Concurrent sweep 단계를 거쳐 객체를 정리합니다.
Initial Mark, Final Remark 단계에서만 stop-the-world가 일어나기 때문에 다른 단계에서 애플리케이션 스레드가 같이 실행되 응답이 빠른 장점이 있습니다.
하지만 단점도 존재합니다.
GC의 풀 사이클 자체는 Parallel Old GC 보다 길다.
다른 GC 방법보다 메모리와 CPU를 더 많이 사용한다.
Compaction 단계가 기본적으로 제공되지 않아 메모리 단편화가 발생한다.
CMS GC는 CMF(Concurrent Mode Failure)가 생겨 Parallel old GC로 바뀌고 stop-the-world가 일어나기도 한다.
- G1 GC
기존 GC와 다르게 Young, Old 영역이 아니라 아예 다른 방식으로 실행된다. heap을 여러 영역으로 나누고 각 영역에 대해서만 GC를 수행해 기존 방식보다 훨씬 빠르다.
각 리전별로 살아있는 객체가 없는 리전을 먼저 회수하기 때문에 메모리 확보가 빠르고, 이 때문에 조기 승격이나 급격히 할당률이 늘어나는 것을 방지할 수 있다. G1이란 이름도 살아있는 객체가 없는 리전(Garbage)을 먼저(First) 수거하기때문에 G1이란 이름을 붙였다.
리전 안에서 GC가 일어나고 리전 안에서 compaction이 일어난다.
다음에는 GC에 관여할 수 있도록 하는 Java Reference에 대해 알아 봐야겠다
참조링크
'JAVA' 카테고리의 다른 글
[Java Test] 테스트 (0) | 2022.09.03 |
---|---|
[Java] concurrentHashMap (0) | 2022.05.01 |
[Java] 자바 동기화 컬렉션(Synchronized Collection) (0) | 2022.04.25 |
[Java] 동등성, 동일성 (0) | 2022.04.11 |
[Java] 싱글톤 (0) | 2022.04.10 |