일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Spring
- 2606
- React
- 우선순위큐
- setviewname
- heapq
- 미로탐색
- 파이썬스럽게
- minmax
- WebMvcConfigurer
- 2667
- 2178
- SWEA
- addAttribute
- __name__
- 단지번호붙이기
- JWT
- 삼성소프트웨어
- dfs
- major gc
- 미로탈출
- pep8
- 음료수얼려먹기
- Arecode
- MSSQL
- 이코테
- 화살표함수
- 백준
- 파이썬컨벤션
- BFS
- Today
- Total
하루하루는 성실하게 인생 전체는 되는대로
[JAVA] JVM - Heap Memory와 GC(가비지 콜렉션) 본문
full gc가 동작하여 heap메모리가 95퍼 이상 치솟는 상황이 발생했다.
full gc와 JVM메모리 구조에 대한 개념을 다시한번 집고 넘어가고자 한다.
GC(가비지 콜렉터)
java 어플리케이션에서 사용하지 않는 메모리를 자동으로 수거(=삭제)하는 기능
* 가비지
: java에서 객체=쓰레기(가비지)이다. 하나의 객체가 만들어지면 메모리를 점유하는데, 특정 메소드 수행 완료한 후 필요없어진 객체는 쓰레기(가비지)가 되기 때문.
=> 이 쓰레기 객체, 가비지를 처리하는 작업을 GC라고 한다. 수동으로 관리해줘야하는 c언어와 달리, java에서는 GC 알고리즘이 메모리를 automatic하게 관리해줌. (개발자가 손댈 필요도, 손댈 수도 없음)
* Stop-the-world
: GC를 실행하기 위해, java 어플리케이션의 실행 멈춤. (현재 gc 실행중인 thread 제외한 모든 thread를 멈춤.)
=> minorCG는 보통 0.5초 이내, FullCG는 좀 더 장시간 소요되는데 이동안 사용자 요청이 큐에 쌓여서, FullCG 끝난 후 한번에 처리하면 과부하 걸릴 수 있다. (GC 튜닝이라고 하면, stop-the-world의 시간 줄이는 행위임)
* OutOfMemoryError
: gc해도 더이상 사용 가능한 메모리 영역 없는데 계속 메모리 할당하려고 하면 발생.
GC의 역할
- 메모리 할당
- 사용중인 메모리 인식
- 사용하지 않는 메모리 인식
JVM(Java Virtual Machine)
java와 os 사이에서 중개자 역할 수행.
해당 os에 맞는 JVM을 사용해 os에 구애받지 않고 프로그램 실행하게 해줌.
gc를 사용해 메모리관리 자동 수행.
Stack 기반으로 동작함.
JVM Memory 구조
- 크게 4개 영역 : 클래스 영역, 자바 stack, heap, native 메소드
=> 여기서 가비지 콜렉터에서 다루는 영역 : heap 메모리
JVM Heap 메모리 구조
- 크게 3개 영역 : Young, Old, Perm(permanent)
- YOUNG : Eden + 2 Survivor 로 구성. lifetime 짧은 객체.
=> survivor 둘 중 하나는 항상 비어있다. - OLD : lifetime이 긴 객체.
- PERM : 클래스 객체에 관한 정보를 저장하는 공간. 프로그램 코드 올라가며, 코드 다 로딩되고나면 거의 사용되지 않기 때문에 일정한 수치 유지함.
=> 따라서, 우리가 고려해야할 자바 메모리 영역 : young(1 Eden + 2 Survivor) + old => 총 4개 영역
Heap 메모리 할당
- young은 전체heap의 50퍼보다 약간 작게
- survivor는 전체young의 8분의1 정도
- young이 너무 작으면 젊은 객체가 old로 넘어갈 확률 커지고 major gc 발생확률 높아짐.
- 메모리 Option
- -Xms, -Xmx : heap의 최소, 최대 사이즈
- -XX:NewSize, -XX:MaxNewSize : young의 초기 사이즈, 최대 사이즈
- -XX:NewRatio : old/young인 비율 (ex. 2이면 old가 young의 2배 크기)
- -XX:SurvivorRatio : young/survivor인 비율 (ex. 8이면 young이 survivor의 8배 크기)
- -XX:PermGen, -XX:MaxPermGen : Perm의 초기 사이즈, 최대 사이즈
Minor GC & Major GC & Full GC
- 마이너 GC : Young에서 발생하는 GC
- 메이저 GC : Old, Perm에서 발생하는 GC
- Full GC : minor gc + major gc
두 가지 GC의 상호 작용에 따라 GC 방식이 달라지고, 이는 성능에도 영향을 준다.
* 앞서 언급했듯이, GC 발생하거나 객체가 다른 영역으로 이동할 때 stop-the-world로 인한 애플리케이션 병목 발생하여 성능에 영향 줌.
GC 발생하는 과정
1. 객체 생성되면, Eden 영역에 메모리 지정.
2. Eden에 데이터 꽉차면 minor GC 발생하는데, 이때 살아남은 객체를 전부 survivor로 이동시킴.
=> 두 survivor 중 한쪽 survivor에만 넣어둠. 나머지 한쪽 survivor은 비워둠.
3. minor GC 발생할 때마다, 한쪽 survivor에 넣어뒀던 것과 Eden에서 살아남은 객체는 다른 쪽 survivor로 이동시키면서
survivor 양쪽을 왔다갔다 하게 된다.
4. minor GC 발생하여, 살아남은 객체를 건너편 survivor에 또다시 몽땅 넣으려는데, 살아남은 객체가 survivor 영역의 용량보다 넘치면, 그때는 old로 넘긴다.
=> eden의 용량과 상관없이 young에서 오래 살아남은 객체는 old로 옮김.
: 각 객체가 minor GC에서 살아남은 횟수(=age bit)가 MaxTenuringThreshold 설정값 초과하면, 해당 객체를 old로 이동시킴.
5. old 영역에서 미사용된다고 식별되는 객체는, Full CG를 통해 메모리에서 제거됨.
GC의 종류
* Mark-Sweep-Compaction 알고리즘
: 여러 GC에서 사용되는 기본적인 GC 과정임.
사용되지 않는 객체 식별(Mark) -> 사용되지 않는 객체 제거(Sweep) -> 남은 메모리 파편을 앞에서부터 채워나감(Compaction)
* Mark-Summary-Compaction 알고리즘
: summary 단계에서 이미 GC 수행된 영역에서도 객체를 식별하는 작업 진행. => Old GC 처리량 늘리기 위함.
- Serial GC
: 순차적으로 GC 진행 (왜냐면 과거 리소스 부족할 때는 스레드 하나 뿐이었기 때문에) - Parallel GC
: 멀티스레드로 minor GC 처리하는 스레드를 여러 개로 늘려 좀 더 빠른 동작 가능.
=> serial GC 보다 stop-the-world 시간 줄어듦. - Parallel Old GC
: Parallel GC에서 Old GC 알고리즘 개선한 버전. minor GC 뿐 아니라, Old GC도 병렬로 수행되게 함.
+ Mark-Sweep-Compaction에서 더 개선된, Mark-Summary-Compaction 알고리즘 사용 - CMS GC
: 앞선 GC보다 좀 더 개선된, 그만큼 좀 더 복잡한 방식. STW를 최소화하는데 초점 맞춤.
=> Initial Mark -> Concurrent Mark -> Remark -> Concurrent Sweep
(Compaction은 정말 필요할 때만 사용) - G1 GC(G1 : Garbage First)
: 하드웨어 발전으로 메모리 크기 커짐에 따라, 큰 힙 메모리에 맞는 짧은 GC 시간 보장하기 위해 생겨남.
JVM heap 구조에 특이점이 있음(전체 heap을 region이라는 특정 크기로 나눠서 각 region에 역할(eden, survivor, old) 부여하는 식.
=> initial Mark -> Root Region Scan -> Concurrent Mark -> Remark -> Cleanup -> Copy(=일종의 compaction)
[참고]
https://mirinae312.github.io/develop/2018/06/04/jvm_gc.html
https://donghyeon.dev/java/2020/03/31/%EC%9E%90%EB%B0%94%EC%9D%98-JVM-%EA%B5%AC%EC%A1%B0%EC%99%80-Garbage-Collection/
'JAVA' 카테고리의 다른 글
[JAVA] JWT 인증 적용 (+WebMvcConfigurer와 Interceptor) 구현 (0) | 2022.09.15 |
---|---|
[JWT] JSON Web Token이란 (0) | 2022.09.10 |
[JAVA] 예외처리의 중요성 (0) | 2022.01.20 |