일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Spring
- 백준
- Galera Cluster
- Kafka
- Data Structure
- Java
- 자바
- 컴퓨터구조
- Heap
- redis
- react
- spring webflux
- Algorithm
- 네트워크
- 파이썬
- Proxy
- JavaScript
- 운영체제
- MySQL
- IT
- 디자인 패턴
- JPA
- OS
- C
- mongoDB
- 자료구조
- MSA
- c언어
- 알고리즘
- design pattern
Archives
- Today
- Total
시냅스
Java 가비지 컬렉션 Garbate Collection 정리 본문
GC
- stop the world
- GC를 실행하기 위해 JVM이 애플리케이션의 실행을 멈춤
- gc를 실행하는 쓰레드를 제외한 나머지 쓰레드는 작업을 멈춤
- 어떤 GC 알고리즘을 사용하더라도 꼭 발생
- 대개의 GC 튜닝은 이 시간을 줄이는 것
- 가비지 컬렉터의 실행 조건
- JVM이 OS로부터 메모리를 부여 받고 프로그램을 실행하다가 메모리가 부족하여 OS에게 추가로 메모리를 요청하는 시점에 실행된다.
- 혹은 JVM의 idle time에 실행된다.
- dangling object가 그 대상이다.
- System.gc() 를 호출해선 안된다.
- System.gc() 는 garbage collection 을 실행하는 함수
- 자바에서는 명시적으로 메모리를 지정하여 해제하지 않기 때문에
- 객체를 null 로 지정하거나 System.gc() 를 호출하여 메모리 해제
- 단 System.gc()는 시스템 성능에 매우 큰 영향을 끼치므로 사용해서는 안된다.
- Young 영역과 Old 영역
- 가비지 컬렉터는 두 가지 가정 하에 만들어졌다.
- 대부분의 객체는 금방 접근 불가능 상태(unreachable)가 된다.
- 오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다.
- 이러한 가설을 weak generational hypothesis라 한다.
- 위 가정을 최대한 살리기 위해 HotSpot VM(JVM의 종류)에서는 물리적 공간을 Young과 Old 영역으로 크게 2개로 나눴다.
- Young (Young Generation) 영역
- 새롭게 생성한 객체의 대부분은 여기에 위치한다.
- 대부분의 객체가 금방 접근 불가능 상태(e.g. for문 안의 객체, 함수 내부의 객체 등)가 되기 때문에 young 영역에서 생성되었다가 사라진다.
- 여기에서 사라질 때 minor gc가 발생했다고 말한다.
- Old (Old Generation) 영역
- 접근 불가능 상태로 되지 않아 Young 영역에서 살아남은 객체는 여기로 복사된다.
- 대부분 Young 영역보다 크게 할당한다.
- 크기가 큰 만큼 Young 영역보다 GC는 적게 발생
- 여기에서 사라질 때 major gc가 발생했다고 한다.
- Permanent (Permanent Generation) 영역
- method 영역이라고 하기도 한다.
- 객체나 억류된 문자열 정보(String.inter == string pool 에 넣는다)를 저장하는 곳
- old 영역에서 살아남은 객체가 영원히 저장되는 공간은 아니다
- 이 영역에서 GC가 발생해도 major gc count에 포함된다.
- java 8 에선 metaspace로 교체됨
- classloader가 현재까지 로드한 class들의 metadata가 저장되는 공간
- metaspace 는 jvm이 아닌 OS에서 관리하는 native 메모리 영역
- heap이 아니라 native 메모리(시스템의 기본 메모리) 영역에 위치
- default로 제한된 크기를 갖고 있지 않고, 필요한 만큼 늘어남
- java 8 부턴 permgen 관련 jvm 옵션은 무시한다.
- 가비지 컬렉터는 두 가지 가정 하에 만들어졌다.
- Old 영역에 있는 객체가 Young 영역의 객체를 참조하는 경우
- Old 영역은 512 바이트의 chunk로 되어있는 카드 테이블이 있다.
- old 영역 객체가 young 영역의 객체를 참조할 때 마다 카드 테이블에 정보를 표시한다.
- Young 영역의 GC를 실행할 때에는 old 영역에 있는 모든 객체의 참조를 확인하지 않고 카드 테이블만 뒤져서 GC 대상인지 식별한다.
- Young 영역의 구성
- Young 영역은 3개의 영역으로 나뉜다.
- Eden 영역
- Survivor 영역 (2개)
- 각 영역의 처리 절차 순서는 다음과 같다.
- 새로 생성한 대부분의 객체는 Eden 영역에 위치한다.
- Eden 영역에서 GC가 한 번 발생한 후 살아남은 객체는 Survivor 영역 중 하나로 이동한다.
- 위의 Survivor 영역으로 객체가 계속 쌓인다.
- 하나의 Survivor 영역이 가득 차면 그 중에서 살아남은 객체를 다른 Survivor 영역으로 이동한다.
- 그리고 가득 찬 survivor 영역은 아무 데이터도 없는 상태로 된다.
- 이 과정을 반복하다가 계속해서 살아남아 있는 객체는 Old 영역으로 이동하게 된다.
- Survivor 영역 중 하나는 반드시 비어 있는 상태로 남아야 한다.
- 참고
- bump-the-pointer
- 객체를 stack으로 관리하여 메모리 할당 후 맨 위에 넣어 다음 객체 생성 시에 가장 위의 객체를 보고 eden 영역에 적합한지 판단하여 메모리 할당을 빠르게 하는 기술
- TLAB
- 각각의 스레드가 각자의 eden 영역의 작은 덩어리를 가질 수 있게 해서 각 스레드에서 bump-the-pointer 를 사용하더라도 thread safe 하게 만든다
- bump-the-pointer
- Young 영역은 3개의 영역으로 나뉜다.
- Old 영역에 대한 GC
- 방식은 jdk 7 기준으로 5가지이다.
- Serial GC
- 운영 서버에서 절대 사용해선 안된다
- 싱글코어 전용
- Parallel GC
- mark - sweep - compacting 순서
- Old 영역에 살아 있는 객체를 식별(Mark) 한다
- 그 다음에는 heap의 앞 부분부터 확인하여 살아 있는 것만 남긴다 (Sweep)
- 각 객체들이 연속되게 쌓이도록 힙의 가장 앞 부분부터 채워 객체가 존재하는 부분과 객체가 없는 부분으로 나눈다. (compacting)
- Parallel Old GC(Parallel Compacting GC)
- mark - summary - compacting
- 위의 sweep과 summary가 다른 점은 앞서 gc를 수행한 영역에 대해서 별도로 살아 있는 객체를 식별한다는 점과 약간 더 복잡한 단계를 거친다는 점이다.
- Concurrent Mark & Sweep GC (CMS)
- 위의 mark - sweep 을 concurrent 하게 실행한다
- initial mark 에서 객체를 확인하고
- concurrent mark에서 스레드가 실행 중인 상태에서 확인하고
- remark에서 새로 추가되거나 끊긴 객체를 확인하여
- concurrent sweep 으로 다른 스레드가 실행되는 와중에 정리하는 작업을 실행한다.
- 다른 GC보다 리소스 사용량이 많고, compacting이 기본적으로 제공되지 않는다.
- Serial GC
- 방식은 jdk 7 기준으로 5가지이다.
- G1(Garbage First) GC
- java 9 이후부터 default gc
- heap을 일정크기의 region으로 잘게 나누어서 관리
- 어떤 부분은 old, 어떤 부분은 young
- 각 바둑판에 eden, survivor, old를 따로 두어 이동시키거나 삭제함
- G1 GC는 바둑판의 각 영역에 객체를 할당하고 gc를 실행한다. 그러다가, 해당 영역이 꽉 차면 다른 영역에서 객체를 할당하고 gc를 실행한다.
정리
- mark and sweep
- root로 부터 연결이 되어있는 객체는 놔두고 끊어진 객체들은 지운다
- old 영역에서 실행된다.
- 따라서 mark and sweep 혹은 major gc 시간을 짧게 유지해야 한다.
- young 영역에서는 카드 테이블을 조회하여 참조가 없으면 minor gc를 실행한다.
- age-bit
- young 영역에 있는 객체가 old 영역으로 넘어가는 기준
- 높을 수록 오래도록 참조될 객체로 old 영역에 넘어갈 확률이 높다
- 참조 지역성의 원리로 minor gc가 훨씬 자주 일어난다.
- age-bit
'Java, Spring' 카테고리의 다른 글
Java Equals와 HashCode, == 와 차이 (0) | 2023.02.11 |
---|---|
Java Annotation Processor 정리 (0) | 2023.02.11 |
Java 함수형 프로그래밍 (0) | 2023.02.06 |
Spring 트랜잭션 전파 정리 (0) | 2022.09.03 |
Spring 선언적 트랜잭션과 AOP, 프록시 객체에 대한 이해 (0) | 2022.09.03 |
Comments