JVM Troubleshooting
프로덕션 환경에서는 예상치 못한 메모리 누수나 스레드 교착 상태 (Deadlock)로 인해 시스템이 멈추는 현상이 발생할 수 있다.
OutOfMemoryError (OOM) 트러블슈팅
섹션 제목: “OutOfMemoryError (OOM) 트러블슈팅”OOM은 단순히 힙 메모리가 부족할 때만 발생하는 것이 아니라, 다양한 메모리 영역과 한계 상황에서 발생한다.
| OOM 메시지 | 주요 원인 | 발생 영역 | 해결 방향 |
|---|---|---|---|
Java heap space | 가장 흔한 메모리 누수 또는 과도한 객체 생성 | 힙 (Heap) 영역 | 힙 덤프 분석 후 누수 지점 코드 수정 또는 힙 크기 증가 |
Metaspace | 로드된 클래스 메타데이터가 너무 많음 (동적 클래스 로딩 과다) | 메타스페이스 (Metaspace) | 불필요한 동적 클래스 생성(CGLib, 리플렉션) 원인 파악 및 크기 조정 |
GC Overhead limit exceeded | GC 실행에 98% 이상의 시간을 소비하지만 회수된 메모리가 2% 미만 | 전체 힙 | 메모리가 꽉 차서 시스템이 죽기 직전이므로 즉각적인 힙 덤프 분석 필요 |
자주 보고되는 실제 OOM 발생 패턴은 다음과 같다.
Java heap space: DB에서 수백만 건의 데이터를 페이징 (Paging)이나 스트림 (Stream) 방식 없이 한 번에 조회하여 힙 메모리에 적재하다가 발생Metaspace: 런타임에 동적 프록시 (CGLib)를 매번 새로 생성하여 캐싱하지 않는 잘못된 코드를 작성하거나, 외부 스크립트를 실행할 때 클래스로더가 무한정 메타데이터를 적재하다가 발생GC Overhead limit exceeded: 애플리케이션 레벨의 전역 캐시에 데이터를 무한정 담아두고 만료 정책을 설정하지 않은 상황에서, 트래픽 폭주로 메모리가 꽉 차 GC가 끝없이 도는 과정에서 발생
힙 덤프 (Heap Dump) 분석
섹션 제목: “힙 덤프 (Heap Dump) 분석”메모리 누수를 추적하려면 OOM 발생 순간의 힙 상태를 캡처해야 한다.
- 획득 방법:
-XX:+HeapDumpOnOutOfMemoryErrorJVM 옵션을 활성화하여 OOM 발생 시 자동으로.hprof덤프 파일이 생성되도록 설정 - 분석 방법: Eclipse MAT (Memory Analyzer Tool) 또는 VisualVM을 사용하여 덤프 파일을 로드
- 주요 확인 지표:
- Dominator Tree: 힙 메모리를 가장 많이 점유하고 있는 객체와 그 참조 트리를 확인
- Leak Suspects Report: 툴이 자동으로 계산한 메모리 누수 의심 지점 확인
스레드 덤프 (Thread Dump) 분석
섹션 제목: “스레드 덤프 (Thread Dump) 분석”애플리케이션이 Hang (응답 없음) 상태에 빠지거나 CPU 사용률이 비정상적으로 치솟을 때는 스레드 상태를 확인해야 한다.
- 획득 방법:
jstack <pid>명령어를 통해 현재 실행 중인 프로세스의 모든 스레드 스택 트레이스를 캡처 - 활용 시나리오: 3~5초 간격으로 스레드 덤프를 연속으로 3회 이상 수집하여 상태 변화를 대조 분석
주요 스레드 상태와 의심 증상
섹션 제목: “주요 스레드 상태와 의심 증상”스레드 덤프 분석 시 스레드의 상태값과 락 (Lock) 대기 구조를 파악하는 것이 핵심이다.
| 현상 | 주요 상태값 | 발생 원인 및 의심 증상 | 확인 및 조치 방법 |
|---|---|---|---|
| 데드락 (Deadlock) | BLOCKED | 두 개 이상의 스레드가 서로의 락을 획득하기 위해 무한 대기 중인 상태 | 덤프 최하단의 “Found one Java-level deadlock” 메시지 확인 후 락 획득 순서 점검 |
| 스핀 락 (무한 루프) | RUNNABLE | 스레드는 계속 실행 상태이나 실제로는 동일한 비즈니스 로직(예: 잘못 짜인 while문)에 갇혀 있음 | CPU 점유율이 100%일 때, 연속된 덤프에서 동일 스택 트레이스 위치에 멈춰 있는지 확인 |
| 리소스 병목 | WAITING / TIMED_WAITING | 수많은 스레드가 DB 커넥션 풀 등 제한된 자원을 얻기 위해 대기 | 풀 크기(Connection Pool)를 조절하거나 응답 지연(Slow Query)의 원인 파악 |
JFR (Java Flight Recorder)
섹션 제목: “JFR (Java Flight Recorder)”JFR은 오버헤드가 극히 적은 (일반적으로 1% 미만) JVM 내장 프로파일링 도구로, 프로덕션 환경에서 상시 켜두고 진단할 수 있다.
- 활용: 특정 시간 동안의 GC 지연 시간, 스레드 블로킹, 메모리 할당률, 파일/네트워크 I/O 병목 등을 종합적으로 기록
- 분석: JMC (Java Mission Control) 도구를 사용하여 수집된 덤프 파일 (
.jfr)을 시각화하고 문제를 드릴다운하여 분석