일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 제네릭
- springboot
- Jenkins
- 동시성
- 트랜잭션
- 재고 시스템
- method area
- backend
- JDK14
- 지연로딩
- 리팩터링
- 상태패턴
- java
- 주문
- GithubActions
- Redis
- 웹캐시
- nonclustered index
- JPA
- 부하테스트
- 카카오 화재
- Ehcache
- Spring Data Redis
- ci/cd
- 공변
- Metaspace
- B+TREE
- CaffeineCache
- lazyloading
- JAVA8
- Today
- Total
NDM
[Java] 자바 동작 원리와 JVM 3편 : Garbage Collector 본문
https://ndm-tech.tistory.com/22
https://ndm-tech.tistory.com/3
을 통해 JVM에 대해 알아보았으니, GC에 대해 알아보겠습니다.
목차는 다음과 같습니다.
- GC란?
- GC 알고리즘
- GC 동작 원리
GC란?
GC(Garbage Collection)란, "JVM상에서 더 이상 사용되지 않는 데이터가 할당되어있는 메모리를 해제시켜주는 장치"
입니다. C나 C++의 경우, 개발자가 직접 메모리를 해제해줘야 하지만, Java는 GC가 불필요한 메모리를 대신 해제해주기 때문에 직접 해제할 일이 없습니다.
- 개발자의 실수로 인한 메모리 누수
- 메모리 이중 해제
- 해제된 메모리에 접근
으로 비롯된 에러를 막을 수 있다는 장점이 있고,
- GC의 타이밍을 정확하게 알 수 없으며
- GC의 대상을 색출해내고, 실제로 삭제하는 일이 모두 오버헤드
라는 단점이 있습니다. 특히, GC의 타이밍을 제대로 알 수 없음으로 인해 실시간 개발 환경에는 거의 쓰이지 않습니다
다음으로 알고리즘을 알기 전에, 먼저 머리에 넣어두어야 할 2가지 키워드가 있습니다.
- Stop The World
STW로 불리는 Stop The World는, JVM이 GC를 실행하기 위해 어플리케이션의 실행을 멈추는 것 을 뜻합니다. GC는 별도의 스레드로 동작하기 때문에, GC가 동작하면 JVM은 GC를 실행시키는 스레드를 제외한 모든 스레드를 정지시킵니다.
때문에 GC가 자주 동작할수록, 안쓰는 객체들이 지워져 메모리의 가용 공간이 늘어난다고 생각할 수 있으나, 동시에 이 Stop-The-World 시간도 늘어나게 되는 셈이므로, 효율적으로 GC를 동작시키면서, 이 Stop-The-World의 시간을 줄이는 것이 모든 JVM기반 언어 개발자들의 숙명이라고도 할 수 있겠습니다.
- Weak Generation Hypothesis
대부분의 객체는 금방 UnReachable 상태가 되며,
오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다는 가설입니다.
즉, 대부분의 객체는 일회성이며, 오랫동안 남아있는 경우가 드물다는 것이죠.
바로 이 가설이 GC의 대상인 Heap 영역을 Old 와 Young 영역으로 나눈 이유가 됩니다.
Young Generation
- 새로운 객체가 생성되는 공간입니다
- 대부분의 객체가 이 공간에서 생성되었다가, 삭제됩니다.
- 이 영역에서 일어나는 GC를 Minor GC라고 합니다
Old Generation
- Young Generation에서 일정 시간 이상 살아남은 객체들이 이동되는 공간입니다
- Young 영역보다 크게 할당되며, 여기서 일어나는 GC를 Major GC(Full GC)라고 합니다.
UnReachable 상태에 대해 자세히 알고 싶은 분들은 https://ndm-tech.tistory.com/3 포스팅을 참고해주세요!
GC 알고리즘
- Referencing Count
Root Space는 Static변수나 Stack 변수 등 Heap의 객체를 참조하고 있는 공간입니다.
그리고 Reference Count는 "얼마나 많은 객체로부터 참조받고 있느냐" 를 뜻합니다.
만약 0이 된다면, 어떤 객체도 해당 객체를 참조할 수 있는 방법이 없다는 뜻이니 GC의 대상이 됩니다.
단, 노란색 동그라미에서 맨 위 객체의 위 화살표를 끊는다고 상상해 봅시다.
그럼 노란색 동그라미 속의 객체들은 따로 떨어져서 서로가 서로만 참조하는 순환 참조를 이루게 됩니다.
이런 경우, 항상 Referencing Count는 1로 유지되고, 삭제 대상이 되지 않는다는 문제점이 있습니다.
- Mark And Sweep
사실 https://ndm-tech.tistory.com/3
포스팅에서 알아봤던 개념이 바로 Mark And Sweep 입니다.
Root Space에서 그래프 순회를 통해 접근 가능하면 Reachable, 그렇지 않으면 UnReachable 상태로 Mark해두고, GC시점에 UnReachable 상태의 객체들을 지우는 방식이죠. Referencing Count 알고리즘의 순환 참조 문제를 해결할 수 있지만 단점도 있습니다.
의도적으로 특정 시간에 GC를 실행해야 한다 는 것인데, 이는 애플리케이션 실행과 병행되어야 한다는 것을 뜻하죠
GC 동작 방식
Heap은 크게 Young, Old라는 두 영역으로 나눠집니다
Young Generation은 새로운 객체가 생성되어 존재하는 영역이며, Old Generation은 살아남은 객체들이 모이는 곳입니다.
더 자세히 알아보면
- 새로 생성된 객체는 Young Generation의 Eden에 위치하게 되고
- Eden이 꽉 차면 MinorGC가 작동됩니다
- 거기서 살아남은 객체들은 Survivor 영역으로 이동을 하고요
- Survivor 0, 1두 영역이 꽉 찰때마다 MinorGC가 작동하고, 두 영역을 왔다갔다 하게 됩니다.
- 이렇게 살아남은 객체들이 영역을 옮길때마다 age bit가 1씩 증가하는데, 일정 수준의 age bit가 되면 이제는 Young Generation이 아닌 Old Generation으로 이동하게 됩니다.
- 그리고 Old Generation에서도 GC가 일어나는데 이를 MajorGC(FullGC)라고 하는 것이고, 이때 STW가 발생합니다
다시 한번 말씀드리지만, 개발자들은 대부분의 객체의 생명주기가 짧으며, 일회성이라는 것을 파악했습니다. 때문에 Old와 Young이라는 영역으로 Heap을 분할함으로써 GC의 종류도 나누게 되었고, STW를 최소화 시키기 위한 노력을 진행했다는 것이 중요합니다
참조
https://steady-coding.tistory.com/590
https://tecoble.techcourse.co.kr/post/2021-08-30-jvm-gc/
'Java' 카테고리의 다른 글
Java Record 클래스를 알아보자 (0) | 2023.06.26 |
---|---|
[Java] lambda에서 final변수만 사용 가능한 이유 - 멀티스레드의 비밀 (0) | 2022.09.15 |
[Java] Java Exception과 Spring Transaction (0) | 2022.08.06 |
[Java] Java8 MetaSpace (0) | 2022.08.05 |
[Java] Java Generic은 어떻게 동작할까? (0) | 2022.05.09 |