목차
- OOM (Out of Memory)
(1) OOM의 발생 원인 - OOM과 Garbage Collector의 관계
- Dump를 뜨다
- MAT 사용법
- 참고 자료
0. OOM (Out of Memory)
업무를 보다보면 팀 메신저 방에 이따금씩 OOM에 관련된 내용이 공유된다.
메모리가 부족한 에러이니 덤프를 떠서 메모리 누수의 원인을 분석 후 해결방안을 찾으면 되지만, 제대로 이해하고 있다는 느낌이 들지 않았다.
또한 덤프를 뜨는게 해결 방안의 전부인것 같지는 않았다.
이 기회에 관련 용어 및 해결 방안을 정리해보고자 한다.
(1) OOM의 발생 원인
공식문서의 언급에 따르면 OOM은 Java의 Heap 메모리가 부족하여 더 이상 가용한 메모리가 없을 경우 발생한다.
대표적으로 아래 2가지 사례로 발생한다.
- 장시간에 걸쳐 서서히 메모리 잠식(leak)으로 인한 OOM
- ex : Cache(어떤 데이터를 여러 쓰레드가 공유해서 사용하는 경우) leak
- 순간적으로 과도한 메모리 할당으로 인해 발생
- ex : 과도한 데이터 조회 (100만건, 200만건 씩 조회해서 메모리를 들고 있는 경우)
- ex : 과도한 데이터 조작 (String)
(2) 해결 방안
원인에 따라 해결 방안은 다양한데, 아래 몇 가지 예시가 있다.
- 제일 쉽고 빠른 해결 방법은 서버 재기동
- 당장은 해결이 될 수 있으나, 장기적으로는 원인을 파악하지 못해 OOM이 재발될 수 있다.
- Heap Memory의 크기 증가
- GC(Garbage Collector) Time의 증가를 동반하기 때문에 충분한 사전 테스트가 요구된다.
- GC Time의 증가 이유는 Heap Memory가 증가하다보니 더 많은 메모리를 스캔하고, 이에 따라 GC가 수집을 할지 말지에 대한 체크가 더 빈번하게 발생하기 때문이다.
- Heap dump 분석
- OOM이 발생한 시점에 생성된 Heap Dump 분석을 기반으로 많은 Memory를 사용하거나 Memory Leak을 유발하는 로직을 찾을 수 있다.
- 부하 테스트 및 모니터링
- 대표적으로 관련 툴로 JMeter, Visual VM이 있다.
- 이 방법은 OOM을 사전에 예방하는 방향성에 더 적합하다.
1. OOM과 Garbage Collector의 관계
Garbage Collector(GC)의 YGC / FGC
Java는 Young 영역
과 Old 영역
으로 메모리를 분할하는데, 신규로 생성되는 객체는 Young 영역
에 보관, 오래 살아있는 객체는 Old 영역
에 보관한다.
Young 영역
은 Eden
, S0
, S1
3개의 영역으로 구분되는데, 뒤에 2개는 Survivor 공간
이라고도 불린다.
신규 생성 객체는 Eden 영역
에 보관되고, Eden 영역
이 100% 차게 되면 사용되지 않는 객체는 제거하고 사용되는 객체는 S0
으로 이동한다. 이 과정을 Minor GC
라고 한다.
또 다시 Eden 영역
이 100%가 되면 Eden 영역
과 S0 영역
에서 사용하지 않는 객체는 제거, 남은 객체를 S1
으로 이동한다.
이때 여러번 Minor GC
가 발생했는데도 S1
에 오래 살아남는 객체가 있으면, 이 객체는 Old 영역
으로 보내진다.
문제는 Old 영역
이 100%가 되면 메이저 GC (= Full GC) 가 발생하게 되는데, 이 때, JVM의 동작을 멈추고 Old 영역
의 메모리를 정리하게 된다. 결론적으로 메이저 GC가 발생하게 되면 프로그램의 동작이 멈추기 때문에 큰 이슈가 발생할 수 있다.
2. Dump를 뜨다
Dump를 뜨는데에는 다양한 툴과 방법이 있다.
대표적으로 Eclipse의 오픈 소스인 MAT
을 많이 활용하는데, 우선 해당 툴을 사용하기 전에 아래 조건이 만족어야 한다.
💡 힙이 터지기 전에(= OOM이 발생하기 전에) dump를 자동으로 생성하는 JVM 옵션 적용
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump/directory/your-dump-file.hprof
이렇게 하면 힙이 터졌을 때 해당 디렉토리에 덤프 파일(=hprof)이 생성된다.
힙이 터지기 전 뿐만 아니라, 현재 돌아가고 있는 JVM의 dump를 뜨는 방법도 있다.
💡 현재 돌아가고 있는 JVM의 dump를 뜨는 jamp 명령어
//pid가 1234인 자바 프로세스의 heapdump 파일을 대상 디렉토리에 생성
jmap -dump:format=b,file=/tmp/heapdump.hprof 1234
3. MAT 사용법
티끌모아개발님의 자바 HeapDump 생성하는 방법, MAT 이용해 메모리릭 분석하기 - 클릭!
위 블로그 링크에 MAT에 사용 방법이 자세하게 나와있으니, 필요시 참고하도록 하자.
4. 참고 자료
'👩🏻💻 Programming > Etc' 카테고리의 다른 글
IntelliJ에서 Gradle Build가 실패할 때 해결책 (0) | 2024.10.29 |
---|---|
Kafka - Classpath is empty 이슈 (0) | 2024.09.22 |
Docker compose 명령어 (0) | 2023.01.13 |
Curl 개념 및 사용법 (0) | 2022.02.10 |
Git blame 사용법 (0) | 2022.02.04 |