콘텐츠로 이동

JVM Troubleshooting

프로덕션 환경에서는 예상치 못한 메모리 누수나 스레드 교착 상태 (Deadlock)로 인해 시스템이 멈추는 현상이 발생할 수 있다.

OOM은 단순히 힙 메모리가 부족할 때만 발생하는 것이 아니라, 다양한 메모리 영역과 한계 상황에서 발생한다.

OOM 메시지주요 원인발생 영역해결 방향
Java heap space가장 흔한 메모리 누수 또는 과도한 객체 생성힙 (Heap) 영역힙 덤프 분석 후 누수 지점 코드 수정 또는 힙 크기 증가
Metaspace로드된 클래스 메타데이터가 너무 많음 (동적 클래스 로딩 과다)메타스페이스 (Metaspace)불필요한 동적 클래스 생성(CGLib, 리플렉션) 원인 파악 및 크기 조정
GC Overhead limit exceededGC 실행에 98% 이상의 시간을 소비하지만 회수된 메모리가 2% 미만전체 힙메모리가 꽉 차서 시스템이 죽기 직전이므로 즉각적인 힙 덤프 분석 필요

자주 보고되는 실제 OOM 발생 패턴은 다음과 같다.

  • Java heap space: DB에서 수백만 건의 데이터를 페이징 (Paging)이나 스트림 (Stream) 방식 없이 한 번에 조회하여 힙 메모리에 적재하다가 발생
  • Metaspace: 런타임에 동적 프록시 (CGLib)를 매번 새로 생성하여 캐싱하지 않는 잘못된 코드를 작성하거나, 외부 스크립트를 실행할 때 클래스로더가 무한정 메타데이터를 적재하다가 발생
  • GC Overhead limit exceeded: 애플리케이션 레벨의 전역 캐시에 데이터를 무한정 담아두고 만료 정책을 설정하지 않은 상황에서, 트래픽 폭주로 메모리가 꽉 차 GC가 끝없이 도는 과정에서 발생

메모리 누수를 추적하려면 OOM 발생 순간의 힙 상태를 캡처해야 한다.

  • 획득 방법: -XX:+HeapDumpOnOutOfMemoryError JVM 옵션을 활성화하여 OOM 발생 시 자동으로 .hprof 덤프 파일이 생성되도록 설정
  • 분석 방법: Eclipse MAT (Memory Analyzer Tool) 또는 VisualVM을 사용하여 덤프 파일을 로드
  • 주요 확인 지표:
    • Dominator Tree: 힙 메모리를 가장 많이 점유하고 있는 객체와 그 참조 트리를 확인
    • Leak Suspects Report: 툴이 자동으로 계산한 메모리 누수 의심 지점 확인

애플리케이션이 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은 오버헤드가 극히 적은 (일반적으로 1% 미만) JVM 내장 프로파일링 도구로, 프로덕션 환경에서 상시 켜두고 진단할 수 있다.

  • 활용: 특정 시간 동안의 GC 지연 시간, 스레드 블로킹, 메모리 할당률, 파일/네트워크 I/O 병목 등을 종합적으로 기록
  • 분석: JMC (Java Mission Control) 도구를 사용하여 수집된 덤프 파일 (.jfr)을 시각화하고 문제를 드릴다운하여 분석

마지막 업데이트:

Java