Garbage Collection이란
가비지 컬렉션이란 자바의 메모리 관리 방법으로 JVM의 Heap영역에서 동적으로 할당된 메모리중 필요 없어진 메모리 객체를 자동으로 주기적으로 제거하는 프로세스이다.
Garbage Collection의 장단점
- 장점
- 메모리 누수를 방지할수있다.
- 이미 해제한 메모리를 다시 해제하거나, 해제한 메모리에 다시 접근하는 오류들을 방지할수있다.
- 단점
- 개발자가 메모리가 언제 해제되는지 정확히 알수가 없다,
- 오버헤드로 인한 성능저하가 발생할수있다.
Garbage Collection 대상
그렇다면 어떤 객체가 GC의 대상이 되는것일까?
객체는 Reachable과 Unreachable 로 나누어지는데 객체가 참조되고 있는 상태면 Reachable, 참조되고있지않으면 Unreachable 이다.
GC는 Unreachable 한 객체들을 주기적으로 제거해준다.
Garbage Collection 알고리즘
GC의 대표적인 알고리즘에는 Reference Counting, Mark and Sweep이 있다.
Reference Counting은 Reference Count라는 숫자가 존재하는데 이는 몇가지 방법으로 해당 객체에 접근 가능한지를 의미한다. Reference Counting은 Reference Count를 계산해서 접근할수 있는 방법이 없으면 즉, Reference Count값이 0이라면 GC 대상이 된다.
하지만 Reference Counting은 순환 참조라는 문제가 발생할수있다.
위와 같이 서로가 서로를 참조하고있기 때문에 Root Space와의 연결이 끊겨도 Reference Count값이 1로 유지 되기 때문에 메모리가 해제되지 못하고 메모리 누수가 발생한다.
Mark and Sweep은 이러한 순환참조 문제를 해결할수있다.
Mark and Sweep은 Root Space에서 순회를 통해 연결된 객체를 찾아내고 연결이 안되어있는 나머지 객체들을 지우는 방식이다. 이후 Compaction을 통해 Heap 영역을 정리해준다.
Mark and Sweep은 순환참조 문제를 해결할수있다는 장점이 있지만, 의도적으로 GC를 실행시켜야하고 이과정에서 GC에게 컴퓨터 리소스를 할당해야하고 성능저하가 생길수있다.
GC의 Root Space
Mark and Sweep 방식은 루트로 부터 해당 객체에 접근이 가능한지가 해제의 기준이 된다.
JVM GC이 Root Space는 Heap 메모리를 영역을 참조하는 meathod area, static, native method stack이다.
Garbage Collection 동작 과정
GC는 JVM의 Heap 영역에서 일어나는데 JVM의 Heap영역은 다음과 같다.
Young generation과 Old generation으로 나누어 지고, Young generation은 Eden, Survival0, Survival1 으로 나누어진다.
먼저 Eden은 새롭게 생성되는 객체들이 할당된다.
처음 객체가 생성되면 Eden 영역에 저장된다.
시간이 지나 Eden영역에 객체가 다 쌓이면 minor GC가 일어나고 이때 살아남은 객체들은 age bit가 1씩 증가하고 Survival0영역에 저장된다.
또 다시 Eden 영역이 가득 차게 되면 minor GC가 다시한번 발생하고 살아남은 객체들은 이번에는 Survival0이 아닌 Survival1에 age bit가 1씩 증가한 상태로 저장된다. ( Survival0 -> Survival1 -> Survival0 반복)
해당 과정을 반복하다 보면 age bit가 특정 숫자 이상으로 증가하게 되고, 특정숫자 이상으로 증가하면 오랫동안 사용될 객체라고 판단하고 Old generation으로 이동시킨다.
시간이 지나 Old generation이 가득차게되면 Old generation에서도 GC가 발생하는데 해당 GC를 Major GC라고한다. Major GC는 시간이 오래걸리기 때문에 이떄 GC를 진행하는 쓰레드를 제외한 모든 쓰레는 멈추게된다. (Stop-the-World)
Stop the World
GC를 수행하기 위해 JVM이 프로그램 실행을 멈추는 현상을 의미한다.
GC를 진행하는 쓰레드를 제외한 모든 쓰레는 멈추게되어 서비스 이용에 차질을 줄수있다.
따라서 STW를 최소화 시켜야한다.
Serial GC - 하나의 쓰레드로 GC를 실행한다. 따라서 STW가 길다.(싱글 스레드 및 Heap이 매우 작을 경우)
Parallel GC - 여러개의 쓰레드로 GC를 실행한다. 멀티코어 환경에서 사용, Java 8의 default GC
Reference
- https://www.youtube.com/watch?v=FMUpVA0Vvjw
- https://rebelsky.cs.grinnell.edu/Courses/CS302/99S/Presentations/GC/
- https://coding-factory.tistory.com/829
'Java , Spring > Java' 카테고리의 다른 글
[Java] call by value, call by reference (0) | 2024.01.18 |
---|---|
[Java] String.valueOf() 와 toString() (0) | 2024.01.17 |
[Java] JIT 컴파일러 (인터프리터와 컴파일) (0) | 2024.01.12 |
[Java] JVM 메모리 구조 (0) | 2024.01.12 |
[Java] String, StringBuffer, StringBuilder 차이 및 장단점 (0) | 2024.01.10 |
댓글